//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Das_Loader_Log_Analysis.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "ChartfxLib_OCX"
#pragma link "FPSpread_OCX"
#pragma resource "*.dfm"
#define REGISTRY 0

TDasLoaderLogAnalysis_Main *DasLoaderLogAnalysis_Main;

AnsiString MDB = "";         //DB file 의 경로와 파일명
AnsiString CurrentDir = "";  //현재의 경로
AnsiString Query = "";       //Query 저장 하는 변수
AnsiString Recipe_sql = "";  //Query에 포할될 Recipe   의 질의
AnsiString Lot_sql = "";     //Query에 포할될 Lot      의 질의
AnsiString Cst_sql = "";     //Query에 포할될 Cst      의 질의
AnsiString DTime_sql = "";   //Query에 포할될 Date Time의 질의
AnsiString Date1 = "", Date2 = "";  //날짜를 문자로 받는 변수
bool       Refer_State_Date    = false;
bool       Refer_State_Recipe  = false;
bool       Refer_State_Lot     = false;
bool       Refer_State_ReciLot = false;
bool       Show_Once           = false;

//---------------------------------------------------------------------------
__fastcall TDasLoaderLogAnalysis_Main::TDasLoaderLogAnalysis_Main(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TDasLoaderLogAnalysis_Main::FormCreate(TObject *Sender)
{
        int i;

        CurrentDir = GetCurrentDir();
        vaSpread2->Row = 0;
        vaSpread2->Col = 1;
        vaSpread2->Text = "RECIPE";
        vaSpread3->Row = 0;
        vaSpread3->Col = 1;
        vaSpread3->Text = "LOT";
        vaSpread4->Row = 0;
        vaSpread4->Col = 1;
        vaSpread4->Text = "CST";
        PageControl1->ActivePage = TabSheet1;
        Export->Enabled = false;
        Import->Enabled = false;
        Delete->Enabled = false;
        TabSheet2->TabVisible = false;
        TabSheet3->TabVisible = false;
        TabSheet4->TabVisible = false;
        TabSheet5->TabVisible = false;

        //MainMenu1->Items->Items[0]->Items[3]->Enabled = false;
        SaveasXSL->Enabled = false;

        DateTimePicker1->Date = Now()-1;
        DateTimePicker3->Date = Now();
        Date1 = DateToStr(DateTimePicker1->Date);
        Date2 = DateToStr(DateTimePicker3->Date);

        AnsiString Registry = "";
        int cnt = 1;

        DWORD dwStyle; //TreeView checkboxes 설정
        dwStyle = ::GetWindowLong(TreeView1->Handle, GWL_STYLE);
        dwStyle |= TVS_CHECKBOXES;
        ::SetWindowLong(TreeView1->Handle, GWL_STYLE, dwStyle);
        ::InvalidateRect(TreeView1->Handle, NULL, true);

        TTreeNode *Node1, *Node2;
        TreeView1->Items->Clear(); // remove any existing nodes

        ////////////////////////////////////////////////////////////////
        if(REGISTRY){
            Registry = "Software\\Mirero System\\Siltron\\DataBase";
            TRegistry *tmpRegi = new TRegistry;
            tmpRegi->RootKey = HKEY_CURRENT_USER;

            if( tmpRegi->OpenKeyReadOnly(Registry)){
                MDB = tmpRegi->ReadString("mdb");
                tmpRegi->CloseKey();
                delete tmpRegi;
                if(!FileExists( MDB)){
                    ShowMessage(MDB + "\n파일을 찾을 수가 없습니다. 데이터 파일을 생성하세요.");
                    OpenDialog1->Title="Create MS Access database";

                    if(OpenDialog1->Execute()){
                        if(FileExists(DasLoaderLogAnalysis_Main->OpenDialog1->FileName)){
                            ShowMessage("File exist and will be recreated");
                            DeleteFile(DasLoaderLogAnalysis_Main->OpenDialog1->FileName);
                        }
                        MDB = DasLoaderLogAnalysis_Main->OpenDialog1->FileName;
                        Create_DB(MDB);

                        TRegistry *Reg = new TRegistry;
                        try
                        {
                            Reg->RootKey = HKEY_CURRENT_USER;
                            if (Reg->OpenKey("Software\\Mirero System\\Siltron\\DataBase", true))
                            {
                                Reg->WriteString("mdb",MDB);
                                Reg->CloseKey();
                            }
                        }
                        __finally
                        {
                            delete Reg;
                        }
                    }
                    else{
                        ShowMessage("기본 DataBase 생성 합니다.");
                        MDB = "C:\\Program Files\\MiRERO\\Siltron3\\DataBase\\LoadData.mdb";
                        Default_Create_DB(MDB);
                    }
                }
            }
            else{             //registry에 정보가 없는 경우
                tmpRegi->CloseKey();
                delete tmpRegi;
                MDB = "C:\\Program Files\\MiRERO\\Siltron3\\DataBase\\LoadData.mdb";
                Default_Create_DB(MDB);
            }
        }
        else{
            char buffer[256];
            getcwd(buffer, 256);
            MDB.sprintf("%s\\DataBase",buffer);
            if (!DirectoryExists(MDB)){    //디렉토리가 있는지 검사한후 없다면
                ForceDirectories(MDB);     // 디렉토리를 만듬
            }
            MDB += "\\LoadData.mdb";
            if(!FileExists(MDB)){
                Create_DB(MDB);
            }

        }
        ///////////////////////////////////////////////////////////////////////////////

        TRegistry *Reg = new TRegistry;
        Reg->RootKey = HKEY_CURRENT_USER;
        Registry.sprintf("Software\\Mirero System\\Siltron\\Folder\\Equipment%d", cnt);
        while( Reg->OpenKeyReadOnly(Registry)){
            if(Reg->ReadString("EquipID")!= ""){
                Node1 = TreeView1->Items->Add(NULL, Reg->ReadString("EquipID"));
                SetTreeCheck(Node1, 1);
            }
            if(!(Reg->ReadString("ProcessNO")== "*" || Reg->ReadString("ProcessNO")== "" )){
                Node2 = TreeView1->Items->AddChild(Node1, Reg->ReadString("ProcessNO"));
                SetTreeCheck(Node2, 1);
            }
            if(!(Reg->ReadString("ProcessNO2")== "*" || Reg->ReadString("ProcessNO2")== "" )){
                Node2 = TreeView1->Items->AddChild(Node1, Reg->ReadString("ProcessNO2"));
                SetTreeCheck(Node2, 1);
            }
            Reg->CloseKey();
            Registry.sprintf("Software\\Mirero System\\Siltron\\Folder\\Equipment%d", ++cnt);
        }
        delete Reg;

        if(Show_Once == true){
            Query.sprintf("SELECT DISTINCT RECIPE FROM LD_MAIN WHERE ");
            Query += DTime_Select();
            int i = FQuery(vaSpread2,Query);
            if( i == 1){
                vaSpread2->Col=1;
                vaSpread2->Row=-1;
                vaSpread2->CellType = 10;
                ReadField(vaSpread2);
                CheckAll(vaSpread2,1);
            }
            if(i == 2){
                GETRECIPE->Caption = "검색 데이터 없음";
            }
            Show_Once = false;
        }
}
//---------------------------------------------------------------------------
void __fastcall TDasLoaderLogAnalysis_Main::Change_DTime(TObject *Sender)
{
        GETRECIPE->Caption = "GET RECIPE";
        vaSpread2->MaxRows = 0;
        vaSpread3->MaxRows = 0;
        vaSpread4->MaxRows = 0;        
}
//---------------------------------------------------------------------------
void __fastcall TDasLoaderLogAnalysis_Main::GETRECIPEClick(TObject *Sender)
{
        int i;
        AnsiString   str = "";
        vaSpread2->Hide();
        SetCurrentDir(CurrentDir);

        Query.sprintf("SELECT DISTINCT RECIPE FROM LD_MAIN WHERE ");
        Query += DTime_Select();
        Query += " AND ";
        if( (str = Get_Eqp_Process(TreeView1)) == ""){
            vaSpread2->Show();
            ShowMessage("Checking EQP-PROCESS!!");
            return;
        }
        Query += "(" + str + ")";

        i = FQuery( vaSpread2,Query);
        if(i == 1){
            vaSpread2->Col=1;
            vaSpread2->Row=-1;
            vaSpread2->CellType = 10;
            ReadField(vaSpread2);
            CheckAll(vaSpread2,1);
        }
        if(i == 2){
            GETRECIPE->Caption = "검색 데이터 없음";
            vaSpread2->MaxRows = 0;
            vaSpread3->MaxRows = 0;
            vaSpread4->MaxRows = 0;
        }
        vaSpread2->Show();
}
//---------------------------------------------------------------------------
void __fastcall TDasLoaderLogAnalysis_Main::RECIPE_Head_Click(
      TObject *Sender, long Col, long Row)
{
        TvaSpread *temp = dynamic_cast<TvaSpread *>(Sender);
        vaSpread3->MaxRows = 0;
        vaSpread4->MaxRows = 0;
        Header_Click( temp, Col, Row);
        Edit3->Text = "";
        Edit4->Text = "";
        Edit5->Text = "";
}
//---------------------------------------------------------------------------
void __fastcall TDasLoaderLogAnalysis_Main::Recipe_Select(TObject *Sender,
      WORD &Key, TShiftState Shift)
{
        if(Key != 229){
            TEdit *str = (TEdit *)Sender;
            vaSpread2->Col = 1;
            vaSpread3->MaxRows = 0;
            vaSpread4->MaxRows = 0;
            for(int i=0; i < vaSpread2->MaxRows; i++){
                vaSpread2->Row = i+1;
                if( vaSpread2->TypeCheckText == str->Text) vaSpread2->Value = "1";
                else vaSpread2->Value = "0";
            }
        }        
}
//---------------------------------------------------------------------------
void __fastcall TDasLoaderLogAnalysis_Main::RecipeToLotClick(
      TObject *Sender)
{
        AnsiString str = "";
        vaSpread3->Hide();
        Query.sprintf("SELECT DISTINCT LOT FROM LD_MAIN WHERE ");

        Recipe_sql = "";
        if(vaSpread2->MaxRows == 0){
            vaSpread3->Show();
            ShowMessage("Recipe is NULL!!");
            return;
        }
        if(GetCheckState(vaSpread2)){
            if(!GetCheckList(vaSpread2, Recipe_sql)){
                vaSpread3->Show();
                ShowMessage("Checking Recipe!!");
                return;
            }
            Query += Recipe_sql + " AND ";
        }
        Query += DTime_Select() + " AND ";
        if( (str = Get_Eqp_Process(TreeView1)) == ""){
            vaSpread2->Show();
            ShowMessage("Checking EQP-PROCESS!!");
            return;
        }
        Query += "(" + str + ")";
        if(FQuery(vaSpread3,Query)==1){
            vaSpread3->Col=1;
            vaSpread3->Row=-1;
            vaSpread3->CellType = 10;
            ReadField(vaSpread3);
            CheckAll(vaSpread3,1);
        }
        vaSpread3->Show();        
}
//---------------------------------------------------------------------------
void __fastcall TDasLoaderLogAnalysis_Main::Lot_Head_Click(TObject *Sender,
      long Col, long Row)
{
        TvaSpread *temp = dynamic_cast<TvaSpread *>(Sender);
        vaSpread4->MaxRows = 0;
        Header_Click( temp, Col, Row);
        Edit4->Text = "";
        Edit5->Text = "";        
}
//---------------------------------------------------------------------------
void __fastcall TDasLoaderLogAnalysis_Main::LOT_Select(TObject *Sender,
      WORD &Key, TShiftState Shift)
{
        if(Key != 229){
            TEdit *str = (TEdit *)Sender;
            vaSpread3->Col = 1;
            vaSpread4->MaxRows = 0;
            for(int i = 0; i < vaSpread3->MaxRows; i++){
                vaSpread3->Row = i+1;
                if( vaSpread3->TypeCheckText == str->Text) vaSpread3->Value = "1";
                else vaSpread3->Value = "0";
            }
        }        
}
//---------------------------------------------------------------------------
void __fastcall TDasLoaderLogAnalysis_Main::LotToCSTClick(TObject *Sender)
{
        AnsiString str = "";
        vaSpread4->Hide();

        Query.sprintf("SELECT DISTINCT CST FROM LD_MAIN WHERE ");

        Recipe_sql = "";
        if(vaSpread2->MaxRows == 0){
            vaSpread4->Show();
            ShowMessage("Recipe is NULL!!");
            return;
        }
        if(GetCheckState(vaSpread2)){
            if(!GetCheckList(vaSpread2, Recipe_sql)){
                vaSpread4->Show();
                ShowMessage("Checking Recipe!!");
                return;
            }
            Query += Recipe_sql + " AND ";
        }

        Lot_sql = "";
        if( vaSpread3->MaxRows == 0){
            vaSpread4->Show();
            ShowMessage("LOT is NULL!!");
            return;
        }
        if( GetCheckState( vaSpread3)){
            if(!GetCheckList( vaSpread3, Lot_sql)){
                vaSpread4->Show();
                ShowMessage("Checking Lot!!");
                return;
            }
            Query += Lot_sql + " AND ";
        }

        Query += DTime_Select();
        Query += " AND ";
        if( (str = Get_Eqp_Process(TreeView1)) == ""){
            vaSpread4->Show();
            ShowMessage("Checking EQP-PROCESS!!");
            return;
        }
        Query += "(" + str + ")";
        if(FQuery(vaSpread4,Query)){
            vaSpread4->Col=1;
            vaSpread4->Row=-1;
            vaSpread4->CellType = 10;
            ReadField(vaSpread4);
            CheckAll(vaSpread4,1);
        }
        vaSpread4->Show();
}
//---------------------------------------------------------------------------
void __fastcall TDasLoaderLogAnalysis_Main::CST_Head_Click(TObject *Sender,
      long Col, long Row)
{
        TvaSpread *temp = dynamic_cast<TvaSpread *>(Sender);
        Header_Click( temp, Col, Row);
        Edit5->Text = "";        
}
//---------------------------------------------------------------------------
void __fastcall TDasLoaderLogAnalysis_Main::Full_Screen_BTClick(
      TObject *Sender)
{
        Full_Screen_BT->Enabled = false;
        TChart_Full_Screen* Chart_Full_Screen = new TChart_Full_Screen(this);
        Chart_Full_Screen->Show();        
}
//---------------------------------------------------------------------------
void __fastcall TDasLoaderLogAnalysis_Main::ImportClick(TObject *Sender)
{
        AnsiString str = "INSERT INTO LD_MAIN (DTIME,RECIPE,LOT,CST,WAFER,EQP,PROCESS) VALUES (";
        AnsiString insert_query="";
        int rownum = 0;

        if (MessageDlg("데이터 베이스에 입력 하시겠습니까?", mtConfirmation, TMsgDlgButtons() << mbYes << mbNo, 0) == mrYes){
            DB_Connect();
            while( Get_Null_Row(vaSpread1,++rownum)){
                insert_query = str + Get_Spread_Value( vaSpread1, 8, rownum);
                Sql_Query(insert_query);
            }
        }        
}
//---------------------------------------------------------------------------
void __fastcall TDasLoaderLogAnalysis_Main::ExportClick(TObject *Sender)
{
        AnsiString str = "";
        SaveDialog1->Title="Save MS Office Excel";

        if(SaveDialog1->Execute())
        {
            str = "("+Date1 + " " + Date2 + ")";
            if (vaSpread1->ExportToExcel(WideString(SaveDialog1->FileName), WideString(str), WideString("")))
                ShowMessage("Export complete.");
            else
                ShowMessage("Export did not succeed.");
        }
}
//---------------------------------------------------------------------------
void __fastcall TDasLoaderLogAnalysis_Main::DeleteClick(TObject *Sender)
{
        int i, count, Header_Select = 0;
        TVariant c, r, c2, r2;
        Block * Row;
        AnsiString temp = "";
        if( vaSpread1->IsBlockSelected || vaSpread1->SelectionCount)
        {
        // Set the background color for each cell
        // block to blue
            if(RowHeader_Selecting_State(vaSpread1)){
                if (MessageDlg("선택된 ROW를 삭제 하시겠습니까?", mtConfirmation, TMsgDlgButtons() << mbYes << mbNo, 0) == mrYes){
                    AnsiString str = "DELETE from LD_MAIN where NUM = ", Delete_sql = "";
                    count = vaSpread1->SelectionCount;
                    Row = new Block[count];
                    vaSpread1->Row = 0;
                    vaSpread1->Col = 1;
                    temp = vaSpread1->Text;
                    if(temp == "NUM")DB_Connect();
                    for( i=0; i < count; i++)
                    {
                        Delete_sql = "";
                        vaSpread1->GetSelection(i, &c, &r, &c2, &r2);
                        if(c.lVal == -1){  //Row Header 인경우만
                            Header_Select++;
                            Row[i].start = r.lVal;
                            Row[i].rows = r2.lVal+1 - r.lVal;
                            vaSpread1->Col = 1;
                            for(int row = r.lVal; row<=r2.lVal; row ++){
                                vaSpread1->Row = row;
                                Delete_sql = str + vaSpread1->Text;
                                if(temp == "NUM")Sql_Query(Delete_sql);
                            }
                        }
                    }

                    quick_sort( Row, 0,  Header_Select-1);
                    for( i = 0; i < Header_Select; i++)
                    {
                        vaSpread1->DeleteRows(Row[i].start, Row[i].rows);
                        vaSpread1->MaxRows -= Row[i].rows;
                    }
                delete[] Row;
                }
            }
            else{
                ShowMessage("삭제할 Row의 Header를 선택 하세요.");
            }
        }
        else{
            ShowMessage("삭제할 Row의 Header를 선택 하세요.");
        }
}
//---------------------------------------------------------------------------
void __fastcall TDasLoaderLogAnalysis_Main::PageControl1Change(
      TObject *Sender)
{
        if(TabSheet2->Showing){
            if(Refer_State_Date){
                DAY_CHART_VIEW();
                Refer_State_Date = false;
            }
        }
        if(TabSheet3->Showing){
            if(Refer_State_Recipe){
                RECIPE_CHART_VIEW();
                Refer_State_Recipe = false;
            }
        }
        if(TabSheet4->Showing){
            if(Refer_State_Lot){
                LOT_CHART_VIEW();
                Refer_State_Lot = false;
            }
        }
        if(TabSheet5->Showing){
            if(Refer_State_ReciLot){
                RECIPE_LOT_CHART_VIEW();
                Refer_State_ReciLot = false;
            }
        }
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------



















//---------------------------------------------------------------------------
// Data Base를 Create 하는 함수
void __fastcall TDasLoaderLogAnalysis_Main::Create_DB(AnsiString DB_file_name)
{

        int i = 0;
        AnsiString *DB_Create;
        DB_Create = new AnsiString[7];

        DB_Create[0] = "CREATE TABLE LD_MAIN (NUM AUTOINCREMENT(1,1) NOT NULL   PRIMARY KEY  , DTIME TEXT (14), RECIPE text (20), LOT TEXT (20), CST TEXT (13), WAFER TEXT (20), EQP TEXT (10), PROCESS TEXT(10));";
        DB_Create[1] = "CREATE INDEX RECIPE  ON LD_MAIN(RECIPE);";
        DB_Create[2] = "CREATE INDEX LOT     ON LD_MAIN(LOT);";
        DB_Create[3] = "CREATE INDEX DTIME   ON LD_MAIN(DTIME);";
        DB_Create[4] = "CREATE INDEX CST     ON LD_MAIN(CST);";
        DB_Create[5] = "CREATE INDEX EQP     ON LD_MAIN(EQP);";
        DB_Create[6] = "CREATE INDEX PROCESS ON LD_MAIN(PROCESS);";


        if (Catalog.IsEmpty())
        {
            Catalog=Variant::CreateObject("ADOX.Catalog");
        }
        else
        {
            Catalog=GetActiveOleObject("ADOX.Catalog");
        }
        if (Catalog.IsEmpty())
        {
            ShowMessage("Unable to find ADODB-Recordset.");
            return ;
        }
        Catalog.Exec(Function("Create") << ("Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+ DB_file_name));

        while(i<7){
            try{
                commandobject=Variant::CreateObject("ADODB.Recordset");
            }
            catch(EOleSysError &err){
                Application->MessageBox("Could not create Recordset object",err.Message.c_str(),MB_OK);
                Application->Terminate();
                return ;
            }
            if(commandobject.IsNull()){
                ShowMessage("Could not connect to ADO");
                Application->Terminate();
                return ;
            }

            commandobject.Exec(PropertySet("CacheSize") << 50);
            commandobject.Exec(PropertySet("Source") << DB_Create[i++]);
            commandobject.Exec(PropertySet("ActiveConnection") << ("Provider=Microsoft.Jet.OLEDB.4.0;Data Source= " + MDB));
            commandobject.Exec(PropertySet("CursorType") << adOpenKeyset);
            commandobject.Exec(PropertySet("LockType") << adLockOptimistic);

            try{
                commandobject.Exec(Function("Open"));
            }
            catch(EOleSysError &err){
                Application->MessageBox(("Could not open - " + Query).c_str(),err.Message.c_str(),MB_OK);
                return ;
            }
        }
        delete[] DB_Create;
        commandobject = Unassigned;

}

//---------------------------------------------------------------------------
// Query의 결과를 Spread Header에(Title) 뿌려 주는 함수  ReadField 함수로 각각의 cell의 값을 저장함
int __fastcall TDasLoaderLogAnalysis_Main::FQuery(TvaSpread *Spread,AnsiString Query)
{
        FieldsBr    = Unassigned;
        RecordSetDB = Unassigned;
        VariantClear(RecordSetDB);
        VariantInit(RecordSetDB);
        try{
            if (RecordSetDB.IsEmpty())
            {
                RecordSetDB=Variant::CreateObject("ADODB.Recordset");
            }
            else
            {
                RecordSetDB=GetActiveOleObject("ADODB.Recordset");
            }
            if (RecordSetDB.IsEmpty())
            {
                ShowMessage("Unable to find ADODB-Recordset.");
                RecordSetDB = Unassigned;
                return 0;
            }
        }

        catch(EOleSysError &err){
            Application->MessageBox("Could not create Recordset object",err.Message.c_str(),MB_OK);
            Application->Terminate();
            RecordSetDB = Unassigned;
            return 0;
        }
        if(RecordSetDB.IsNull()){
            ShowMessage("Could not connect to ADO");
            Application->Terminate();
            RecordSetDB = Unassigned;
            return 0;
         }

        RecordSetDB.Exec(PropertySet("CacheSize") << 50);
        RecordSetDB.Exec(PropertySet("Source") << Query);
        RecordSetDB.Exec(PropertySet("ActiveConnection") << ("Provider=Microsoft.Jet.OLEDB.4.0;Data Source= " + MDB));
        RecordSetDB.Exec(PropertySet("CursorType") << adOpenKeyset);
        RecordSetDB.Exec(PropertySet("LockType") << adLockOptimistic);
        try{
            RecordSetDB.Exec(Function("Open"));
        }
        catch(EOleSysError &err){
            Application->MessageBox(("Could not open - " + Query).c_str(),err.Message.c_str(),MB_OK);
            RecordSetDB = Unassigned;
            return 0;
        }

        Variant Fields = RecordSetDB.Exec(PropertyGet("Fields"));
        Variant Count  = Fields.Exec(PropertyGet("Count"));
        Variant RC     = RecordSetDB.Exec(Function("RecordCount"));
        int RecordCount=RC;
        if(!RecordCount){
            return 2;
        }
        if(RecordSetDB.Exec(PropertyGet("EOF"))){
            ShowMessage("No correct records");
            RecordSetDB = Unassigned;
            Fields      = Unassigned;
            Count       = Unassigned;
            RC          = Unassigned;
            return 0;
        }
        FieldsBr=RecordSetDB.Exec(PropertyGet("Fields"));

        int count=FieldsBr.Exec(PropertyGet("Count"));

        for(int inum=0;inum < count; ++inum)
        {
            Variant Field=FieldsBr.Exec(Function("Item") << inum);
            AnsiString Text1;
            Text1 = Field.Exec(PropertyGet("Name"));  //테이블의 필드명을 Column Header에 뿌려준다
            Spread->Row  = 0;
            Spread->Col  = inum+1;
            Spread->Text = Text1;
        }
        Fields      = Unassigned;
        Count       = Unassigned;
        RC          = Unassigned;
        return 1;
}

//---------------------------------------------------------------------------
// Spread에 sql질의의 결과를  각각의 Cell값을 뿌려주는 함수
void __fastcall TDasLoaderLogAnalysis_Main::ReadField(TvaSpread *Spread)
{

        long column = 0;
        FieldsBr=RecordSetDB.Exec(PropertyGet("Fields"));

        int count=FieldsBr.Exec(PropertyGet("Count"));
        Spread->MaxRows = 0;
        while(!RecordSetDB.Exec(PropertyGet("EOF")))
        {
            column++;
            Spread->MaxRows++;
            for(int inum=0;inum < count; ++inum)
            {
                Variant Field=FieldsBr.Exec(Function("Item") << inum);
                Variant AS=Field.Exec(PropertyGet("ActualSize"));
                if(AS.IsNull()){
                    Spread->Row  = column;
                    Spread->Col  = inum+1;
                    Spread->Text = "";
                    continue;
                }

                int ActSiz=AS;
                if ( ActSiz <= 0 ){
                    Spread->Row = column;
                    Spread->Col = inum+1;
                    Spread->Text = "";
                    continue;
                }

                Variant Value1;
                Value1=Field.Exec(PropertyGet("Value"));
                if(Value1.IsNull()){
                    Spread->Row = column;
                    Spread->Col = inum+1;
                    Spread->Text = "";
                }
                else {
                    Spread->Row = column;
                    Spread->Col = inum+1;
                    if( Spread->CellType == 10){
                        Spread->TypeCheckText = Value1;
                    }
                    else{
                        Spread->Text = Value1;
                    }
                }
            }
        //Variant Field =
        RecordSetDB.Exec(Function("MoveNext"));
        }
        RecordSetDB = Unassigned;

        for(long inum=0; inum < count; ++inum)
        {
            Spread->Col = inum + 1;
            Spread->Row = -1;
            Spread->ColWidth[inum+1] = Spread->MaxTextColWidth[inum+1] + 2;
            if( Spread->CellType == 1) Spread->TypeHAlign = 2;
        }

}
//---------------------------------------------------------------------------
// Tree의 각 chekcbox가 check 상태를 지정하는 함수  Index를 이용
int __fastcall TDasLoaderLogAnalysis_Main::SetTreeCheck(int iIndex, int iState)
{
        TV_ITEM tvi;
        tvi.mask = TVIF_HANDLE | TVIF_STATE;
        tvi.hItem = TreeView1->Items->Item[iIndex]->ItemId;
        tvi.stateMask = TVIS_STATEIMAGEMASK;
        tvi.state = ((iState + 1) << 12);
        SNDMSG(TreeView1->Handle, TVM_SETITEM, 0, reinterpret_cast<LPARAM>(&tvi));
        return GetTreeCheck(TreeView1->Items->Item[iIndex]);
}

//---------------------------------------------------------------------------
// Tree의 각 chekcbox가 check 상태를 지정하는 함수  Node를 이용
int __fastcall TDasLoaderLogAnalysis_Main::SetTreeCheck(TTreeNode* pNode, int iState)
{
        TV_ITEM tvi;
        tvi.mask = TVIF_HANDLE | TVIF_STATE;
        tvi.hItem = pNode->ItemId;
        tvi.stateMask = TVIS_STATEIMAGEMASK;
        tvi.state = ((iState + 1) << 12);
        SNDMSG(TreeView1->Handle, TVM_SETITEM, 0, reinterpret_cast<LPARAM>(&tvi));
        return GetTreeCheck(pNode);
}
//---------------------------------------------------------------------------
//  기본 DATA BASE를 생성하는 함수
void __fastcall TDasLoaderLogAnalysis_Main::Default_Create_DB(AnsiString FileName)
{
        TRegistry *Reg = new TRegistry;

        try
        {
            Reg->RootKey = HKEY_CURRENT_USER;
            if (Reg->OpenKey("Software\\Mirero System\\Siltron\\DataBase", true))
            {
                Reg->WriteString("mdb",FileName);
                Reg->CloseKey();
            }
        }
        __finally
        {
            delete Reg;
        }
        if (!FileExists(FileName)) {
            Create_DB(FileName);
        }
}
//---------------------------------------------------------------------------
// Tree의 각 chekcbox가 check된 상태를 얻어오는 함수
int __fastcall TDasLoaderLogAnalysis_Main::GetTreeCheck(TTreeNode* pItem)
{
        TV_ITEM tvi;

        tvi.mask = TVIF_HANDLE | TVIF_STATE;
        tvi.hItem = pItem->ItemId;
        tvi.stateMask = TVIS_STATEIMAGEMASK;
        SNDMSG(TreeView1->Handle, TVM_GETITEM, 0, reinterpret_cast<LPARAM>(&tvi));
        return ((tvi.state >> 12) - 1);
}
//---------------------------------------------------------------------------
// 검색 기간을 DTime 변수에 sql질의로 저장 하는 함수
AnsiString  __fastcall TDasLoaderLogAnalysis_Main::DTime_Select(void)
{

        AnsiString DTime = "", date1 = "", date2 = "";
        date1 = FormatDateTime("yyyymmdd", DateTimePicker1->Date);
        date1 +=FormatDateTime("hhnnss",   DateTimePicker2->Time);
        date2 = FormatDateTime("yyyymmdd", DateTimePicker3->Date);
        date2 +=FormatDateTime("hhnnss",   DateTimePicker4->Time);

        if(date1 < date2){
            Date1 = DateToStr(DateTimePicker1->Date);
            Date2 = DateToStr(DateTimePicker3->Date);
            DTime += "( DTIME >= '";
            DTime += date1;
            DTime += "' AND DTIME <= '";
            DTime += date2;
            DTime += "' )";
        }
        else{
            Date2 = DateToStr(DateTimePicker1->Date);
            Date1 = DateToStr(DateTimePicker3->Date);
            DTime += "( DTIME >= '";
            DTime += date2;
            DTime += "' AND DTIME <= '";
            DTime += date1;
            DTime += "' )";
        }
        return DTime;

}
//---------------------------------------------------------------------------
// Spread의 Cell이 CheckBox인경우에 Value값이 "1"이면 Check 상태가 된다.
void __fastcall TDasLoaderLogAnalysis_Main::CheckAll(TvaSpread *Spread,int inum)
{
        Spread->Col = inum;
        Spread->Row = -1;  //전체 column에 대해 적용
        Spread->Value = "1";
}
//---------------------------------------------------------------------------
//  TreeView에 Check된 EQP와 Process를 sql 질의에 맞게 (where절) Parser 하는 함수
AnsiString __fastcall TDasLoaderLogAnalysis_Main::Get_Eqp_Process(TTreeView *TreeView)
{
        AnsiString TempQuery = "";
        int i = 0, preLevel = 2;

        while( i < TreeView->Items->Count){
            if ( GetTreeCheck( TreeView->Items->Item[i])){    //체크 된 경우
                switch(preLevel - TreeView->Items->Item[i]->Level){
                    case -1:
                    TempQuery +="( PROCESS = '"+ TreeView->Items->Item[i]->Text + "' ";
                    break;
                    case 0:
                    TempQuery +="OR PROCESS = '"+ TreeView->Items->Item[i]->Text + "'";
                    break;
                    case 1:
                    TempQuery +=")) OR ( EQP = '"+ TreeView->Items->Item[i]->Text + "' AND ";
                    break;
                    case 2:
                    TempQuery +="( EQP = '"+ TreeView->Items->Item[i]->Text + "' AND ";
                    break;
                }
                preLevel =  TreeView->Items->Item[i]->Level;
            }
            i++;
        }
        if( TempQuery != "") TempQuery += "))";
        return TempQuery;
}
//---------------------------------------------------------------------------
// Spread가 Check_Box상태일때 Column Header를 click 할 때 전체 선택 또는 해체 기능을 하는 함수
void __fastcall TDasLoaderLogAnalysis_Main::Header_Click(TvaSpread *Spread, long Col, long Row)
{

        Spread->Hide();
        Spread->Col = Col;
        Spread->Row = Row;
        if(Col == 1 && Row == 0){
            int count = 0;
            Spread->Col = 1;
            for(int i=0; i < Spread->MaxRows; i++){
                Spread->Row = i + 1;
                AnsiString RowValue = Spread->Value;
                if ( RowValue == "1"){
                    count++;
                    break;
                }
            }

            if(count == 0){
                CheckAll( Spread, 1);
                Spread->ClearSelection( );
            }
            else{
                UnCheckAll( Spread, 1);
                Spread->ClearSelection( );
            }
        }
        Spread->Show();

}
//---------------------------------------------------------------------------
// Spread의 Cell이 CheckBox인경우에 Value값을 "0"이면 UnCheck 상태가 된다.
void __fastcall TDasLoaderLogAnalysis_Main::UnCheckAll(TvaSpread *Spread,int inum)
{
        Spread->Col=inum;
        Spread->Row=-1;   //전체 column에 대해 적용
        Spread->Value = "0";
}
//---------------------------------------------------------------------------
// Spread에서 column 이 1일때 check된 column이 하나라도 있는 경우 true를 return하는 함수
bool __fastcall TDasLoaderLogAnalysis_Main::GetCheckState(TvaSpread *Spread)
{
        Spread->Col = 1;
        for(int i=0; i< Spread->MaxRows; i++){
            Spread->Row=i+1;
            AnsiString RowValue = Spread->Value;
            if( RowValue != "1"){
                return true;
            }
        }
        return false;
}

//---------------------------------------------------------------------------
// Spread에서 Check된 값들 모두를 sql의 in 문에 포함 시켜 주는 함수 (where 절에서 OR 조건문을 대신 한다)
bool __fastcall TDasLoaderLogAnalysis_Main::GetCheckList(TvaSpread *Spread, AnsiString &Query)
{

        int count = 0;
        AnsiString Temp = "";
        Spread->Row = 0;
        Spread->Col = 1;
        Temp = Spread->Text;

        Query = Temp + " in ( ";
        for(int i = 0; i < Spread->MaxRows; i++){
            Spread->Row = i + 1;
            AnsiString RowValue = Spread->Value;
            if ( RowValue == "1"){
                count++;
                Query += "'";
                Query += Spread->TypeCheckText;
                Query += "',";
            }
        }
        if(count > 0){
            Query = Query.SubString(  1,Query.Length()-1);
            Query +=")";
            return true;
        }
        else {
            return false;
        }
}
//---------------------------------------------------------------------------
// TreeNode에서 한 Node를 선택시 그 Node이하의 전 Node를 모두 선택 상태로 지정하는 함수
TTreeNode* __fastcall TDasLoaderLogAnalysis_Main::SetAllSubNode(TTreeNode* ParentNode, TTreeNode* Node)
{
        TTreeNode* TempNode = NULL;
        SetTreeCheck(Node,GetTreeCheck(ParentNode));
        if(ParentNode != Node){
            TempNode = Node->getFirstChild();     //자식이 있는경우
            if(TempNode){
                SetAllSubNode( ParentNode, TempNode);
            }
            else{                                 //자식이 없는 경우
                TempNode = Node->getNextSibling();//형제가 있는 경우
                if(TempNode){
                    SetAllSubNode( ParentNode, TempNode);
                }
                else{                             //자식도 형제도 없는  골치 아픈경우
                    do{
                        TempNode = Node->Parent;
                        if(TempNode != ParentNode){
                            TempNode = TempNode->getNextSibling();
                            if(TempNode != NULL)SetAllSubNode( ParentNode, TempNode);
                            else{
                                }
                        }
                    }while(ParentNode != TempNode);
                    return TempNode;
                }
            }
        }
        return TempNode;
}
//---------------------------------------------------------------------------
// TreeNode에서 parameta로 주어진 Node의 모든 sibling의 check상태가 uncheck인지를  판별하는 함수
int  __fastcall TDasLoaderLogAnalysis_Main::Get_All_Sibling(TTreeNode* Node)
{
        TTreeNode* PreNode, * NextNode;
        PreNode = Node->getPrevSibling();
        while(PreNode != NULL){
          if(GetTreeCheck(PreNode))return 1;
          else  PreNode = PreNode->getPrevSibling();
        }
        NextNode = Node->getNextSibling();
        while(NextNode != NULL){
          if(GetTreeCheck(NextNode))return 1;
          else NextNode = NextNode->getNextSibling();
        }
        return 0;
}
//---------------------------------------------------------------------------
// DataBase연결 함수
void __fastcall TDasLoaderLogAnalysis_Main::DB_Connect(void)
{
        FieldsBr    = Unassigned;
        RecordSetDB = Unassigned;
        VariantClear(RecordSetDB);
        VariantInit(RecordSetDB);
        try{
            if (RecordSetDB.IsEmpty())
            {
                RecordSetDB=Variant::CreateObject("ADODB.Recordset");
            }
            else
            {
                RecordSetDB=GetActiveOleObject("ADODB.Recordset");
            }
            if (RecordSetDB.IsEmpty())
            {
                ShowMessage("Unable to find ADODB-Recordset.");
                return ;
            }
        }
        catch(EOleSysError &err){
            Application->MessageBox("Could not create Recordset object",err.Message.c_str(),MB_OK);
            Application->Terminate();
        }

        if(RecordSetDB.IsNull()){
            ShowMessage("Could not connect to ADO");
            Application->Terminate();
        }

        RecordSetDB.Exec(PropertySet("CacheSize") << 50);
        RecordSetDB.Exec(PropertySet("ActiveConnection") << ("Provider=Microsoft.Jet.OLEDB.4.0;Data Source= " + MDB));
        RecordSetDB.Exec(PropertySet("CursorType") << adOpenKeyset);
        RecordSetDB.Exec(PropertySet("LockType") << adLockOptimistic);

}
//---------------------------------------------------------------------------
// Spread의 값을 sql의 in 다음 절에 맞게 문자열 반화 하는 함수
AnsiString __fastcall TDasLoaderLogAnalysis_Main::Get_Spread_Value(TvaSpread *Spread, int MaxCol, int row)
{
        AnsiString str = "";

        for(int i = 2 ; i <= MaxCol; i++){
            Spread->Col = i;
            Spread->Row = row;
            str +="'";
            str += Spread->Text + "',";
        }
        str=str.SubString(  1,str.Length()-1);
        str+=")";
        return str;

}
//---------------------------------------------------------------------------
//  Data Base에 sql 질의 실행 하는 함수
bool  __fastcall TDasLoaderLogAnalysis_Main::Sql_Query(AnsiString Query)
{

        RecordSetDB.Exec(PropertySet("Source") << Query);
        try{
            RecordSetDB.Exec(Function("Open"));
        }
        catch(EOleSysError &err){
            Application->MessageBox(("Could not open - " + Query).c_str(),err.Message.c_str(),MB_OK);
            return false;
        }
        return true;

}
//---------------------------------------------------------------------------
// Spread에서 cell의 값이 Empty인지 판별하는 함수
bool __fastcall TDasLoaderLogAnalysis_Main::Get_Null_Row(TvaSpread *Spread, int row)
{

        Spread->Col = 1;
        Spread->Row = row;

        if(WideString(Spread->Text).IsEmpty())return false;
        else return true;
}
//-----------------------------------------------------------------------------
//  RowHeader의 선택이 하나라도 되었는가를 얻어 내는 함수
bool __fastcall TDasLoaderLogAnalysis_Main::RowHeader_Selecting_State(TvaSpread *Spread)
{
        int i, count;
        TVariant c, r, c2, r2;

        count = Spread->SelectionCount;
        for( i=0; i < count; i++)
        {
            Spread->GetSelection(i, &c, &r, &c2, &r2);
            if(c.lVal == -1)
                return true;
        }
        return false;
}
//---------------------------------------------------------------------------
//  quick sort를 이용 Delete될 칼럼에서 Row의 값이 큰것부터 삭제 할 수 있게 하는 함수
void __fastcall TDasLoaderLogAnalysis_Main::quick_sort(Block Dim[], long lb, long ub)
{
        long a,b;              /* key holder */
        long up, down;
        long temp;           /* temporary variable, used in swapping */

        if (lb >= ub)
        return;

        a = Dim[lb].start;
        b = Dim[lb].rows;
        up = ub;
        down = lb;

        while (down < up)
        {
            while (Dim[down].start >= a && down < ub)         /* scan the keys from left to right */
            down++;
            while (Dim[up].start < a && up >= 0)             /* scan the keys from right to left */
            up--;
            if (down < up)
            {
                temp = Dim[down].start;          /* interchange records */
                Dim[down].start = Dim[up].start;
                Dim[up].start = temp;
                temp = Dim[down].rows;          /* interchange records */
                Dim[down].rows = Dim[up].rows;
                Dim[up].rows = temp;
            }
        }

        Dim[lb].start = Dim[up].start;                /* interchange records */
        Dim[lb].rows = Dim[up].rows;                /* interchange records */
        Dim[up].start = a;
        Dim[up].rows = b;

        quick_sort(Dim, lb, up-1);         /* recursive call - sort first subtable */
        quick_sort(Dim, up+1, ub);         /* recursive call - sort second subtable */
}
//---------------------------------------------------------------------------
//  검색 된 내용을 일별로 Chart를 이용하여 표현해 주는 함수
void __fastcall TDasLoaderLogAnalysis_Main::DAY_CHART_VIEW(void)
{

        TCursor Save_Cursor = Screen->Cursor;

        Screen->Cursor = crHourGlass;    // Show hourglass cursor
        try
        {
            int i, j;
            AnsiString str,date;
            TDateTime DTemp, DTemp1;
            DTemp = StrToDate(Date2);
            DTemp1= StrToDate(Date1);
            int Rang = DTemp - DTemp1;
            Rang ++;
            int process = Get_Process_Count(TreeView1,1);

            AnsiString *Eqp_Process;
            Eqp_Process = new AnsiString [process];
            for(i = 0; i < process; i++){
                str = Get_EQP_Name(TreeView1, 1, i+1);
                Eqp_Process[i] = str + "[" + Get_PROCESS_Name(TreeView1, 1, i+1) + "]";
            }

            double** DayCount = new double*[process];
            for(i=0; i<process; i++){
                DayCount[i] = new double[Rang];
                memset(DayCount[i], 0, sizeof(double)*Rang);
            }

            for(int Row = 0; Row < vaSpread1->MaxRows; Row++){
                vaSpread1->Col = 2;
                vaSpread1->Row = Row+1;
                str = vaSpread1->Text;

                date  = str.SubString(1,4);
                date += "-" + str.SubString(5,2);
                date += "-" + str.SubString(7,2);
                j  = StrToDate(date) - DTemp1;

                vaSpread1->Col = 7;
                vaSpread1->Row = Row + 1;
                str = vaSpread1->Text;
                vaSpread1->Col = 8;
                vaSpread1->Row = Row + 1;
                str = str+ "[" + vaSpread1->Text+"]";
                for(i = 0; i < process; i++){
                    if(str.AnsiCompare(Eqp_Process[i]) == 0){
                        DayCount[i][j]++;
                        break;
                    }
                }
            }

            SaveasXSL->Enabled = false;
            ChartFX1->ToolBar = 1;
            ChartFX1->SerLegBox = true;
            ChartFX1->PointLabels = true;
            ChartFX1->Axis->get_Item(AXIS_Y)->Max = 0;
            ChartFX1->Axis->get_Item(AXIS_Y)->set_Title(WideString("Wafer 수량"));
            ChartFX1->Axis->get_Item(AXIS_Y)->set_Format(0);
            ChartFX1->Axis->get_Item(AXIS_Y)->set_Decimals(0);
            ChartFX1->Axis->get_Item(AXIS_Y)->AutoScale = true;
            ChartFX1->Axis->get_Item(AXIS_X)->LabelValue = 1;
            ChartFX1->Axis->get_Item(AXIS_X)->Min = 0;
            ChartFX1->Axis->get_Item(AXIS_X)->Max = Rang;
            ChartFX1->Axis->get_Item(AXIS_X)->LabelAngle  = 90;
            ChartFX1->OpenDataEx(COD_XVALUES, process, Rang);

            for( i = 0; i < process; i++){
                str = Get_EQP_Name(TreeView1, 1, i + 1);
                str += "[" + Get_PROCESS_Name(TreeView1, 1, i + 1)+"]";
                SetLegendLabel(ChartFX1, i, str);
            }

            for (int nCount = 0; nCount < Rang; nCount++) {
                DTemp=StrToDate(Date1) + nCount;
                ChartFX1->Axis->get_Item(AXIS_X)->set_Label(nCount,WideString(DTemp));
                for( i = 0; i < process; i++){
                    ChartFX1->ValueEx[i][nCount] = DayCount[i][nCount];
                }
            }
            ChartFX1->CloseData(COD_XVALUES);

            // 메모리 해제
            delete[] Eqp_Process;

            for (int y = 0; y < process; y++)
            {
                delete[] DayCount[y];
            }
            delete[] DayCount;

        }

        __finally
        {
            Screen->Cursor = Save_Cursor; // always restore the cursor
        }

}

//---------------------------------------------------------------------------
// 검색된 내용을 Recipe 별로 Chart를 통해 표현하는 함수
void __fastcall TDasLoaderLogAnalysis_Main::RECIPE_CHART_VIEW(void)
{

        TCursor Save_Cursor = Screen->Cursor;

        Screen->Cursor = crHourGlass;    // Show hourglass cursor
        try
        {

            vector<AnsiString> m_vctValue;
            vector<AnsiString> m_EqProValue;
            vector<long> m_Recipe_Count;

            int k, iProcess;
            SaveasXSL->Enabled = false;
            ChartFX2->SerLegBox = true;
            ChartFX2->PointLabels = true;
            ChartFX2->ToolBar = 1;
            ChartFX2->Axis->get_Item(AXIS_Y)->Max = 0;
            ChartFX2->Axis->get_Item(AXIS_Y)->set_Title(WideString("Wafer 수량"));
            ChartFX2->Axis->get_Item(AXIS_Y)->set_Format(0);
            ChartFX2->Axis->get_Item(AXIS_Y)->set_Decimals(0);
            ChartFX2->Axis->get_Item(AXIS_Y)->AutoScale = true;
            ChartFX2->Axis->get_Item(AXIS_X)->LabelValue = 1;
            ChartFX2->Axis->get_Item(AXIS_X)->Min = 0;
            ChartFX2->Axis->get_Item(AXIS_X)->Max = 0;
            ChartFX2->Axis->get_Item(AXIS_X)->LabelAngle  = 90;

            iProcess = Get_Process_Count(TreeView1,1);

            for(k = 0; k < iProcess; k++){
                m_EqProValue.push_back( Get_EQP_Name(TreeView1, 1, k+1) + "\t[" + Get_PROCESS_Name(TreeView1, 1, k+1) + "]");
            }
            sort( m_EqProValue.begin(), m_EqProValue.end());
            for(k = 0; k < iProcess; k++){
                SetLegendLabel(ChartFX2, k, m_EqProValue[k]);
            }

            AnsiString label[2],temp, EqPr;
            for(int x = 1; x <= vaSpread1->MaxRows; x++){//Spread의 각 값을 \t를 구분으로 sort할수 있도록 저장
                vaSpread1->Row = x;
                vaSpread1->Col=3;
                temp = vaSpread1->Text;
                vaSpread1->Col=7;
                temp += "\t" + vaSpread1->Text;
                vaSpread1->Col = 8;
                temp += "\t[" + vaSpread1->Text + "]";
                m_vctValue.push_back(temp);
            }

            int iFull_Count = m_vctValue.size();
            sort( m_vctValue.begin(), m_vctValue.end());
            m_vctValue.push_back("End\t"); //loop 연산의 핀리를 위해 입력
            int iRecipe = 0;
            int iCount = 0;
            int iEqPro = 0;
            int ipos;

            for(int x = 0; x < iFull_Count; x++){
                iCount++;                //각 값이 누적 된다
                if( m_vctValue[x] != m_vctValue[x+1]){
                    ipos = m_vctValue[x].AnsiPos("\t");
                    label[0] = m_vctValue[x].SubString(1, ipos-1);
                    temp = m_vctValue[x].SubString(ipos+1,m_vctValue[x].Length());
                    ipos = m_vctValue[x+1].AnsiPos("\t");
                    label[1] = m_vctValue[x+1].SubString(1, ipos-1);
                    k = 0;
                    while( k < iProcess){
                        if(temp == m_EqProValue[k]){
                            iEqPro = k;
                            break;
                        }
                        k++;
                    }

                    m_Recipe_Count.push_back(iEqPro);
                    m_Recipe_Count.push_back(iRecipe);
                    m_Recipe_Count.push_back(iCount);

                    if( label[0] != label[1]){
                        ChartFX2->Axis->get_Item(AXIS_X)->set_Label(iRecipe++,WideString(label[0]));
                    }
                    iCount = 0;
                }
            }

            double** RecipeCount = new double*[iProcess];
            for(int i=0; i<iProcess; i++){
                RecipeCount[i] = new double[iRecipe];
                memset(RecipeCount[i], 0, sizeof(double)*(iRecipe));
            }
            iCount = m_Recipe_Count.size()/3;
            for(int x = 0; x < iCount; x++){
               RecipeCount[m_Recipe_Count[x*3]][m_Recipe_Count[x*3+1]] = m_Recipe_Count[x*3+2];
            }
            ChartFX2->OpenDataEx(COD_XVALUES, iProcess, iRecipe);
            for (int y = 0; y < iProcess; y++) {
                for( int x = 0; x < iRecipe; x++){
                    ChartFX2->ValueEx[y][x] = RecipeCount[y][x];
                }
            }
            ChartFX2->CloseData(COD_XVALUES);

            // 메모리 해제
            for (int y = 0; y < iProcess; y++)
            {
                delete[] RecipeCount[y];
            }
            delete[] RecipeCount;
        }
        __finally
        {
        Screen->Cursor = Save_Cursor; // always restore the cursor
        }


}

//---------------------------------------------------------------------------
// 검색된 내용을 Lot 별로 Chart를 통해 표현하는 함수
void __fastcall TDasLoaderLogAnalysis_Main::LOT_CHART_VIEW(void)
{

        TCursor Save_Cursor = Screen->Cursor;

        Screen->Cursor = crHourGlass;    // Show hourglass cursor
        try
        {

            vector<AnsiString> m_vctValue;
            vector<AnsiString> m_EqProValue;
            vector<long> m_Lot_Count;

            int k, iProcess;
            SaveasXSL->Enabled = false;
            ChartFX3->SerLegBox = true;
            ChartFX3->PointLabels = true;
            ChartFX3->ToolBar = 1;
            ChartFX3->Axis->get_Item(AXIS_Y)->Max = 0;
            ChartFX3->Axis->get_Item(AXIS_Y)->set_Title(WideString("Wafer 수량"));
            ChartFX3->Axis->get_Item(AXIS_Y)->set_Format(0);
            ChartFX3->Axis->get_Item(AXIS_Y)->set_Decimals(0);
            ChartFX3->Axis->get_Item(AXIS_Y)->AutoScale = true;
            ChartFX3->Axis->get_Item(AXIS_X)->LabelValue = 1;
            ChartFX3->Axis->get_Item(AXIS_X)->Min = 0;
            ChartFX3->Axis->get_Item(AXIS_X)->Max = 0;
            ChartFX3->Axis->get_Item(AXIS_X)->LabelAngle  = 90;

            iProcess = Get_Process_Count(TreeView1,1);

            for(k = 0; k < iProcess; k++){
                m_EqProValue.push_back( Get_EQP_Name(TreeView1, 1, k+1) + "\t[" + Get_PROCESS_Name(TreeView1, 1, k+1) + "]");
            }
            sort( m_EqProValue.begin(), m_EqProValue.end());
            for(k = 0; k < iProcess; k++){
                SetLegendLabel(ChartFX3, k, m_EqProValue[k]);
            }

            AnsiString label[2],temp, EqPr;
            for(int x = 1; x <= vaSpread1->MaxRows; x++){//Spread의 각 값을 \t를 구분으로 sort할수 있도록 저장
                vaSpread1->Row = x;
                vaSpread1->Col=4;
                temp = vaSpread1->Text;
                vaSpread1->Col=7;
                temp += "\t" + vaSpread1->Text;
                vaSpread1->Col=8;
                temp += "\t[" + vaSpread1->Text + "]";
                m_vctValue.push_back(temp);
            }

            int iFull_Count = m_vctValue.size();
            sort( m_vctValue.begin(), m_vctValue.end());
            m_vctValue.push_back("End\t"); //loop 연산의 핀리를 위해 입력
            int iLot = 0;
            int iCount = 0;
            int iEqPro = 0;
            int ipos;

            for(int x = 0; x < iFull_Count; x++){
                iCount++;                //각 값이 누적 된다
                if( m_vctValue[x] != m_vctValue[x+1]){
                    ipos = m_vctValue[x].AnsiPos("\t");
                    label[0] = m_vctValue[x].SubString(1, ipos-1);
                    temp = m_vctValue[x].SubString(ipos+1,m_vctValue[x].Length());
                    ipos = m_vctValue[x+1].AnsiPos("\t");
                    label[1] = m_vctValue[x+1].SubString(1, ipos-1);
                    k = 0;
                    while( k < iProcess){
                        if(temp == m_EqProValue[k]){
                            iEqPro = k;
                            break;
                        }
                        k++;
                    }

                    m_Lot_Count.push_back(iEqPro);
                    m_Lot_Count.push_back(iLot);
                    m_Lot_Count.push_back(iCount);

                    if( label[0] != label[1]){
                        ChartFX3->Axis->get_Item(AXIS_X)->set_Label(iLot++,WideString(label[0]));
                    }
                    iCount = 0;
                }
            }

            double** LotCount = new double*[iProcess];
            for(int i=0; i<iProcess; i++){
                LotCount[i] = new double[iLot];
                memset(LotCount[i], 0, sizeof(double)*(iLot));
            }
            iCount = m_Lot_Count.size()/3;
            for(int x = 0; x < iCount; x++){
               LotCount[m_Lot_Count[x*3]][m_Lot_Count[x*3+1]] = m_Lot_Count[x*3+2];
            }
            ChartFX3->OpenDataEx(COD_XVALUES, iProcess, iLot);
            for (int y = 0; y < iProcess; y++) {
                for( int x = 0; x < iLot; x++){
                    ChartFX3->ValueEx[y][x] = LotCount[y][x];
                }
            }
            ChartFX3->CloseData(COD_XVALUES);

            // 메모리 해제
            for (int y = 0; y < iProcess; y++)
            {
                delete[] LotCount[y];
            }
            delete[] LotCount;
        }
        __finally
        {
        Screen->Cursor = Save_Cursor; // always restore the cursor
        }

}


//---------------------------------------------------------------------------
// 검색된 내용을 Recipe && Lot별로 Chart로 표현
void __fastcall TDasLoaderLogAnalysis_Main::RECIPE_LOT_CHART_VIEW(void)
{

        TCursor Save_Cursor = Screen->Cursor;

        Screen->Cursor = crHourGlass;    // Show hourglass cursor
        try
        {

            vector<AnsiString> m_vctValue;
            vector<AnsiString> m_EqProValue;
            vector<long> m_ReciLot_Count;

            int k, iProcess;
            SaveasXSL->Enabled = false;
            ChartFX4->SerLegBox = true;
            ChartFX4->PointLabels = true;
            ChartFX4->ToolBar = 1;
            ChartFX4->Axis->get_Item(AXIS_Y)->Max = 0;
            ChartFX4->Axis->get_Item(AXIS_Y)->set_Title(WideString("Wafer 수량"));
            ChartFX4->Axis->get_Item(AXIS_Y)->set_Format(0);
            ChartFX4->Axis->get_Item(AXIS_Y)->set_Decimals(0);
            ChartFX4->Axis->get_Item(AXIS_Y)->AutoScale = true;
            ChartFX4->Axis->get_Item(AXIS_X)->LabelValue = 1;
            ChartFX4->Axis->get_Item(AXIS_X)->Min = 0;
            ChartFX4->Axis->get_Item(AXIS_X)->Max = 0;
            ChartFX4->Axis->get_Item(AXIS_X)->LabelAngle  = 90;

            iProcess = Get_Process_Count(TreeView1,1);

            for(k = 0; k < iProcess; k++){
                m_EqProValue.push_back( Get_EQP_Name(TreeView1, 1, k+1) + "\t[" + Get_PROCESS_Name(TreeView1, 1, k+1) + "]");
            }
            sort( m_EqProValue.begin(), m_EqProValue.end());
            for(k = 0; k < iProcess; k++){
                SetLegendLabel(ChartFX4, k, m_EqProValue[k]);
            }

            AnsiString label[2],temp, EqPr;
            for(int x = 1; x <= vaSpread1->MaxRows; x++){//Spread의 각 값을 \t를 구분으로 sort할수 있도록 저장
                vaSpread1->Row = x;
                vaSpread1->Col=3;
                temp = vaSpread1->Text;
                vaSpread1->Col=4;
                temp += "<" + vaSpread1->Text+">";
                vaSpread1->Col = 7;
                temp += "\t" + vaSpread1->Text;
                vaSpread1->Col=8;
                temp += "\t[" + vaSpread1->Text + "]";
                m_vctValue.push_back(temp);
            }

            int iFull_Count = m_vctValue.size();
            sort( m_vctValue.begin(), m_vctValue.end());
            m_vctValue.push_back("End\t"); //loop 연산의 핀리를 위해 입력
            int iReciLot = 0;
            int iCount = 0;
            int iEqPro = 0;
            int ipos;

            for(int x = 0; x < iFull_Count; x++){
                iCount++;                //각 값이 누적 된다
                if( m_vctValue[x] != m_vctValue[x+1]){
                    ipos = m_vctValue[x].AnsiPos("\t");
                    label[0] = m_vctValue[x].SubString(1, ipos-1);
                    temp = m_vctValue[x].SubString(ipos+1,m_vctValue[x].Length());
                    ipos = m_vctValue[x+1].AnsiPos("\t");
                    label[1] = m_vctValue[x+1].SubString(1, ipos-1);
                    k = 0;
                    while( k < iProcess){
                        if(temp == m_EqProValue[k]){
                            iEqPro = k;
                            break;
                        }
                        k++;
                    }

                    m_ReciLot_Count.push_back(iEqPro);
                    m_ReciLot_Count.push_back(iReciLot);
                    m_ReciLot_Count.push_back(iCount);

                    if( label[0] != label[1]){
                        ChartFX4->Axis->get_Item(AXIS_X)->set_Label(iReciLot++,WideString(label[0]));
                    }
                    iCount = 0;
                }
            }

            double** RecipeLotCount = new double*[iProcess];
            for(int i=0; i<iProcess; i++){
                RecipeLotCount[i] = new double[iReciLot];
                memset(RecipeLotCount[i], 0, sizeof(double)*(iReciLot));
            }
            iCount = m_ReciLot_Count.size()/3;
            for(int x = 0; x < iCount; x++){
               RecipeLotCount[m_ReciLot_Count[x*3]][m_ReciLot_Count[x*3+1]] = m_ReciLot_Count[x*3+2];
            }
            ChartFX4->OpenDataEx(COD_XVALUES, iProcess, iReciLot);
            for (int y = 0; y < iProcess; y++) {
                for( int x = 0; x < iReciLot; x++){
                    ChartFX4->ValueEx[y][x] = RecipeLotCount[y][x];
                }
            }
            ChartFX4->CloseData(COD_XVALUES);

            // 메모리 해제
            for (int y = 0; y < iProcess; y++)
            {
                delete[] RecipeLotCount[y];
            }
            delete[] RecipeLotCount;
        }
        __finally
        {
            Screen->Cursor = Save_Cursor; // always restore the cursor
        }
}
//---------------------------------------------------------------------------
// TreeView에서 Check된 Process를  count하는 함수
int __fastcall TDasLoaderLogAnalysis_Main::Get_Process_Count(TTreeView *TreeView, int level)
{

        int i = 0, count = 0;

        while( i < TreeView->Items->Count){
            if( GetTreeCheck(TreeView->Items->Item[i])){
                if( level == TreeView->Items->Item[i]->Level)count++;
            }
            i++;
        }
        return count;
}
//---------------------------------------------------------------------------
// TreeView에서 EQP를 얻어 오는 함수
AnsiString __fastcall TDasLoaderLogAnalysis_Main::Get_EQP_Name(TTreeView *TreeView, int level, int index)
{
        int i = 0, count = 0;

        while( i < TreeView->Items->Count){
            if( GetTreeCheck(TreeView->Items->Item[i])){
                if( level == TreeView->Items->Item[i]->Level) count++;
                if( count == index){
                    return TreeView->Items->Item[i]->Parent->Text;
                }
            }
            i++;
        }
        return "";
}

//---------------------------------------------------------------------------
// TreeView에서 PROCESS를 얻어 오는 함수
AnsiString __fastcall TDasLoaderLogAnalysis_Main::Get_PROCESS_Name(TTreeView *TreeView, int level, int index)
{
        int i = 0, count = 0;

        while( i < TreeView->Items->Count){
            if(GetTreeCheck(TreeView->Items->Item[i])){
                if( level == TreeView->Items->Item[i]->Level)count++;
                    if(count == index){
                    return TreeView->Items->Item[i]->Text;
                }
            }
            i++;
        }
        return "";
}
//---------------------------------------------------------------------------
// ChartFX의 범례 Label을 설정한다.
void __fastcall TDasLoaderLogAnalysis_Main::SetLegendLabel(TChartFX *ChartFX, int iSeriesIndex, AnsiString& strLabel)
{
        WideString wsTitle;
        WideString url = "sent.htm";
        wsTitle = strLabel.c_str();
        ChartFX->SerLeg[iSeriesIndex] = wsTitle.c_bstr();
}
void __fastcall TDasLoaderLogAnalysis_Main::SearchClick(TObject *Sender)
{
        AnsiString   str = "";

        Query.sprintf("SELECT * FROM LD_MAIN WHERE ");
        vaSpread1->Hide();
        vaSpread1->MaxRows = 0;
        Label2->Caption = "0";
        Recipe_sql = "";
        if(vaSpread2->MaxRows == 0){
            ShowMessage("Recipe is NULL!!");
            return;
        }
        if(GetCheckState(vaSpread2)){
            if(!GetCheckList(vaSpread2, Recipe_sql)){
                ShowMessage("Checking Recipe!!");
                return;
            }
            Query += Recipe_sql + " AND ";
        }

        Lot_sql = "";
        if( vaSpread3->MaxRows == 0){
            ShowMessage("LOT is NULL!!");
            return;
        }
        if( GetCheckState( vaSpread3)){
            if(!GetCheckList( vaSpread3, Lot_sql)){
                ShowMessage("Checking Lot!!");
                return;
            }
            Query += Lot_sql + " AND ";
        }

        Cst_sql = "";
        if( vaSpread4->MaxRows == 0){
            ShowMessage("CST is NULL!!");
            return;
        }
        if( GetCheckState( vaSpread4)){
            if(!GetCheckList( vaSpread4, Cst_sql)){
                ShowMessage("Checking CST!!");
                return;
            }
            Query += Cst_sql + " AND ";
        }

        DTime_sql = DTime_Select();
        Query += DTime_sql;

        Query += " AND ";
        if( (str = Get_Eqp_Process(TreeView1)) == ""){
            ShowMessage("Checking EQP-PROCESS!!");
            return;
        }
        Query += "(" + str + ") ORDER BY NUM";
        int m = FQuery( vaSpread1,Query);
        if( m == 1){
            Refer_State_Date    = true;
            Refer_State_Recipe  = true;
            Refer_State_Lot     = true;
            Refer_State_ReciLot = true;

            TabSheet1->Caption = "검색결과";
            PageControl1->ActivePage = TabSheet1;
            TabSheet2->TabVisible = true;
            TabSheet3->TabVisible = true;
            TabSheet4->TabVisible = true;
            TabSheet5->TabVisible = true;
            SaveasXSL->Enabled = true;
            ReadField( vaSpread1);
            vaSpread1->Visible = true;
            Label2->Caption = vaSpread1->MaxRows;
            Import->Enabled = false;
            Export->Enabled = true;
            Delete->Enabled = true;
        }
        vaSpread1->Show();
}
//---------------------------------------------------------------------------

void __fastcall TDasLoaderLogAnalysis_Main::OpenFileXSLClick(
      TObject *Sender)
{
        AnsiString str = "";
        OpenDialog2->Title="Import MS Office Excel";

        if(OpenDialog2->Execute()){

            TVariant varr,varg;
            SAFEARRAYBOUND rgsabound[1];
            rgsabound[0].lLbound = 0;
            rgsabound[0].cElements = 4;
            bool y , z;
            long lg = 0, count=0;
            short x, listcount,handle;

            VariantClear(&varr);
            VariantInit(&varr);
            VariantClear(&varg);
            VariantInit(&varg);
            varg.vt = VT_BSTR;
            varr.vt = VT_ARRAY | VT_BSTR;
            varr.parray = SafeArrayCreate(VT_BSTR,1,rgsabound);

            // Check if file is an Excel file and set result to x
            x = vaSpread1->IsExcelFile(WideString(DasLoaderLogAnalysis_Main->OpenDialog2->FileName));

            // If file is Excel file, tell user, import sheet
            // list, and set result to y
            if (x==1)
            {
                //ShowMessage("File is an Excel file.");
                y = vaSpread1->GetExcelSheetList(WideString( DasLoaderLogAnalysis_Main->OpenDialog2->FileName), varr, &listcount, WideString(""), &handle, TRUE);
                // If received sheet list, tell user, import file,
                // and set result to z
                if (y)
                {
                    //ShowMessage("Got sheet list.");
                    //HRESULT hresult =
                    SafeArrayGetElement(varr.parray, &lg, &varg.bstrVal);
                    VariantInit(&varr);
                    VariantInit(&varg);
                    z = vaSpread1->ImportExcelSheet(handle, 0);
                    // Tell user result based on T/F value of z
                    if (z) {
                        //ShowMessage("Import complete.");
                        TabSheet1->Caption = "Excel Data";
                        PageControl1->ActivePage = TabSheet1;
                        vaSpread1->MaxCols = 8;
                        vaSpread1->Col = 1;
                        if(vaSpread1->MaxRows > 0){
                            while(++count < vaSpread1->MaxRows){
                                vaSpread1->Row = count;
                                AnsiString RowValue = vaSpread1->Value;
                                if( RowValue == ""){
                                    break;
                                }
                            }
                            vaSpread1->MaxRows = --count;
                            Export->Enabled = false;
                            Import->Enabled = true;
                            Delete->Enabled = true;
                            TabSheet2->TabVisible = false;
                            TabSheet3->TabVisible = false;
                            TabSheet4->TabVisible = false;
                            TabSheet5->TabVisible = false;
                        }
                    }
                    else
                    ShowMessage("Import did not succeed.");
                }
                else
                // Tell user cannot obtain sheet list
                ShowMessage("Cannot return information for Excel file.");
            }
            else
            // Tell user file is not Excel file or is locked
            ShowMessage("File is not an Excel file or is locked and cannot be imported.");
        }
}
//---------------------------------------------------------------------------

void __fastcall TDasLoaderLogAnalysis_Main::BackUpDataClick(
      TObject *Sender)
{
        AnsiString str = "";
        SaveDialog2->Title="Back Up DataBase(저장될 파일 이름 지정)";

        if(SaveDialog2->Execute()){
            if (FileExists(MDB)){
                FieldsBr    = Unassigned;
                RecordSetDB = Unassigned;
                VariantClear(RecordSetDB);
                VariantInit(RecordSetDB);

                try{
                    if (RecordSetDB.IsEmpty())
                    {
                        RecordSetDB=Variant::CreateObject("ADODB.Recordset");
                    }
                    else
                    {
                        RecordSetDB=GetActiveOleObject("ADODB.Recordset");
                    }
                    if (RecordSetDB.IsEmpty())
                    {
                        ShowMessage("Unable to find ADODB-Recordset.");
                        RecordSetDB = Unassigned;
                        return ;
                    }
                }
                catch(EOleSysError &err){
                    Application->MessageBox("Could not create Recordset object",err.Message.c_str(),MB_OK);
                    Application->Terminate();
                    RecordSetDB = Unassigned;
                    return ;
                }
                    if(RenameFile( MDB, DasLoaderLogAnalysis_Main->SaveDialog2->FileName)){
                        ShowMessage("BackUp complete.");
                        Create_DB(MDB);
                    }
                    else {
                        ShowMessage("Fault BackUp.");
                    }
                }
            else{
                ShowMessage(MDB + "\n원본 파일이 없습니다.");
            }
        }    
}
//---------------------------------------------------------------------------

void __fastcall TDasLoaderLogAnalysis_Main::OpenDBClick(TObject *Sender)
{
        OpenDialog1->Title="Open MS Access database";

        if(OpenDialog1->Execute())
        {
            if( !FileExists( DasLoaderLogAnalysis_Main->OpenDialog1->FileName)){
                ShowMessage("File is not exist");
                return;
            }
            GETRECIPE->Caption = "GET RECIPE";
            MDB = DasLoaderLogAnalysis_Main->OpenDialog1->FileName;
            PageControl1->ActivePage = TabSheet1;
            vaSpread1->MaxRows = 0;
            vaSpread2->MaxRows = 0;
            vaSpread3->MaxRows = 0;
            vaSpread4->MaxRows = 0;
            Label2->Caption = "0";
            Export->Enabled = false;
            Import->Enabled = false;
            Delete->Enabled = false;
        }        
}
//---------------------------------------------------------------------------

void __fastcall TDasLoaderLogAnalysis_Main::SaveasXSLClick(TObject *Sender)
{
        AnsiString str = "";
        SaveDialog1->Title="Save MS Office Excel";

        if(SaveDialog1->Execute())
        {
            str = "("+Date1 + " " + Date2 + ")";
            if (vaSpread1->ExportToExcel(WideString(DasLoaderLogAnalysis_Main->SaveDialog1->FileName), WideString(str), WideString("")))
                ShowMessage("Export complete.");
            else
                ShowMessage("Export did not succeed.");
        }
}
//---------------------------------------------------------------------------






void __fastcall TDasLoaderLogAnalysis_Main::ExitClick(TObject *Sender)
{
        Close();
}
//---------------------------------------------------------------------------

