Selaa lähdekoodia

Import Excel: use OExport to Import xls/xlsx

MaiXinRong 8 vuotta sitten
vanhempi
commit
57a4c328a9

+ 3 - 3
Forms/MainFrm.pas

@@ -555,7 +555,7 @@ var
 begin
   if HintAndImportTypeSelect(bWithLevelCode, bWithoutGclBills) then
   begin
-    if SelectFile(sFileName, '.xls') then
+    if SelectExcelFile(sFileName) then
     begin
       Importor := Tdei_CustomBills.Create(CurProjectFrame.ProjectData);
       try
@@ -671,7 +671,7 @@ var
   sFileName: string;
   Importor: TBillsPriceExcelImport;
 begin
-  if SelectFile(sFileName, '.xls') then
+  if SelectExcelFile(sFileName) then
   begin
     Importor := TBillsPriceExcelImport.Create(CurProjectFrame.ProjectData);
     try
@@ -687,7 +687,7 @@ var
   sFileName: string;
   Importor: TDealBillsExcelImport;
 begin
-  if SelectFile(sFileName, '.xls') then
+  if SelectExcelFile(sFileName) then
   begin
     Importor := TDealBillsExcelImport.Create(CurProjectFrame.ProjectData);
     try

+ 2 - 2
Frames/BillsCompileFme.pas

@@ -544,7 +544,7 @@ var
 begin
   if TProjectData(FBillsCompileData.ProjectData).CanInsertNormalBills then
   begin
-    if SelectFile(sFileName, '.xls') then
+    if SelectExcelFile(sFileName) then
     begin
       Importor := TDEI_GclBills.Create(TProjectData(FBillsCompileData.ProjectData));
       try
@@ -629,7 +629,7 @@ var
 begin
   if TProjectData(FBillsCompileData.ProjectData).CanInsertNormalBills then
   begin
-    if SelectFile(sFileName, '.xls') then
+    if SelectExcelFile(sFileName) then
     begin
       Importor := TPlaneFxBillsExcelImport.Create(TProjectData(FBillsCompileData.ProjectData));
       try

+ 4 - 2
Units/Connections.pas

@@ -505,8 +505,10 @@ begin
     end;
   finally
     vCon.Free;
-    DeleteFile(PChar(sConnectFile));
-    DeleteFile(PChar(sTempFile));
+    if FileExists(sConnectFile) then
+      DeleteFile(PChar(sConnectFile));
+    if FileExists(sConnectFile) then
+      DeleteFile(PChar(sTempFile));
   end;
 end;
 

+ 22 - 18
Units/DealBillsExcelImport.pas

@@ -4,7 +4,7 @@ unit DealBillsExcelImport;
 interface
 
 uses
-  DetailExcelImport, ProjectData, Classes, sdDB;
+  DetailExcelImport, ProjectData, Classes, sdDB, OExport;
 
 type
   TDealBill = class
@@ -57,8 +57,8 @@ type
 
     FCurRow: Integer;
 
-    function LoadColumnsFromHead: Boolean;
-    procedure LoadDealBills;
+    function LoadColumnsFromHead(ASheet: TExportWorkSheet): Boolean;
+    procedure LoadDealBills(ASheet: TExportWorkSheet);
     procedure WriteDealBills;
   protected
     procedure BeginImport; override;
@@ -102,18 +102,19 @@ end;
 
 procedure TDealBillsExcelImport.Import;
 begin
-  FCurRow := 1;
-  if LoadColumnsFromHead then
+  FCurRow := 0;
+  if LoadColumnsFromHead(OExport.OpenWorkSheet) then
   begin
-    LoadDealBills;
+    LoadDealBills(OExport.OpenWorkSheet);
     WriteDealBills;
   end
   else
     ErrorMessage('导入的Excel格式有误!');
 end;
 
-function TDealBillsExcelImport.LoadColumnsFromHead: Boolean;
+function TDealBillsExcelImport.LoadColumnsFromHead(ASheet: TExportWorkSheet): Boolean;
 var
+  vRow: TExportRow;
   iCol: Integer;
   sColName: string;
 begin
@@ -126,11 +127,12 @@ begin
   FQuantityCol := -1;
   FTotalPriceCol := -1;
 
-  while (not Result) and (FCurRow <= Excel.XlsFile.MaxRow) do
+  while (not Result) and (FCurRow < ASheet.Rows.Count) do
   begin
-    for iCol := 1 to Excel.XlsFile.MaxCol do
+    vRow := ASheet.Rows[FCurRow];
+    for iCol := 0 to vRow.Cells.Count - 1 do
     begin
-      sColName := GetCellValue(Excel.XlsFile, FCurRow, iCol);
+      sColName := GetCellTrimStr(vRow, iCol);
       sColName := StringReplace(sColName, ' ', '', [rfReplaceAll]);
 
       if SameText(sColName, '清单编号') or (Pos('子目号', sColName) > 0) then
@@ -153,7 +155,7 @@ begin
   end;
 end;
 
-procedure TDealBillsExcelImport.LoadDealBills;
+procedure TDealBillsExcelImport.LoadDealBills(ASheet: TExportWorkSheet);
 
   function CheckIsBillsCode(ACode: string): Boolean;
   const
@@ -183,12 +185,14 @@ procedure TDealBillsExcelImport.LoadDealBills;
   end;
 
 var
+  vRow: TExportRow;
   sB_Code, sFilterB_Code: string;
   vDealBill: TDealBill;
 begin
-  while (FCurRow <= Excel.XlsFile.MaxRow) do
+  while (FCurRow < ASheet.Rows.Count) do
   begin
-    sB_Code := GetCellTrimStr(Excel.XlsFile, FCurRow, FB_CodeCol);
+    vRow := ASheet.Rows[FCurRow];
+    sB_Code := GetCellTrimStr(vRow, FB_CodeCol);
     sFilterB_Code := FilterBillsCode(sB_Code);
     if (sFilterB_Code <> '')then
     begin
@@ -196,11 +200,11 @@ begin
       begin
         vDealBill := TDealBill.Create;
         vDealBill.B_Code := sB_Code;
-        vDealBill.Name := GetCellTrimStr(Excel.XlsFile, FCurRow, FNameCol);
-        vDealBill.Units := GetCellTrimStr(Excel.XlsFile, FCurRow, FUnitsCol);
-        vDealBill.Price := GetCellFloat(Excel.XlsFile, FCurRow, FPriceCol);
-        vDealBill.Quantity := GetCellFloat(Excel.XlsFile, FCurRow, FQuantityCol);
-        vDealBill.TotalPrice := GetCellFloat(Excel.XlsFile, FCurRow, FTotalPriceCol);
+        vDealBill.Name := GetCellTrimStr(vRow, FNameCol);
+        vDealBill.Units := GetCellTrimStr(vRow, FUnitsCol);
+        vDealBill.Price := GetCellFloat(vRow, FPriceCol);
+        vDealBill.Quantity := GetCellFloat(vRow, FQuantityCol);
+        vDealBill.TotalPrice := GetCellFloat(vRow, FTotalPriceCol);
         FDealBills.AddDealBill(vDealBill);
       end;
     end;

+ 281 - 263
Units/DetailExcelImport.pas

@@ -4,19 +4,18 @@ interface
 
 uses
   Classes, ProjectData, ScXlsOutput, MCacheTree, XLSAdapter, sdDB,
-  Variants, Forms, Controls;
+  Variants, Forms, Controls, OExport, OExport_VclForms;
 
 type
   TDetailExcelImport = class
   private
     FProjectData: TProjectData;
-    FTempFile: string;
-    FExcel: TXlsOutPut; 
+    FOExport: TOExport;
   protected
-    function GetCellValue(AXlsFile: TXLSFile; ARow, ACol: Integer): string;
-    function GetCellValueFormat(AXlsFile: TXLSFile; ARow, ACol: Integer): string;
-    function GetCellTrimStr(AXlsFile: TXLSFile; ARow, ACol: Integer): string;
-    function GetCellFloat(AXlsFile: TXLSFile; ARow, ACol: Integer): Double;
+    function GetCellStr(ASheet: TExportWorkSheet; ARow, ACol: Integer): string; overload;
+    function GetCellStr(ARow: TExportRow; ACol: Integer): string; overload;
+    function GetCellTrimStr(ARow: TExportRow; ACol: Integer): string;
+    function GetCellFloat(ARow: TExportRow; ACol: Integer): Double;
 
     procedure BeginImport; virtual; abstract;
     procedure EndImport; virtual; abstract;
@@ -29,7 +28,7 @@ type
     procedure ImportFile(const AFileName: string);
 
     property ProjectData: TProjectData read FProjectData;
-    property Excel: TXlsOutPut read FExcel;
+    property OExport: TOExport read FOExport;
   end;
 
   // 平面分项清单格式导入,导入至某项目节节点之下
@@ -56,18 +55,18 @@ type
     FDrawingCol: Integer;
     FMemoCol: Integer;
 
-    procedure LoadXmjLevel1(AXlsFile: TXLSFile);
-    procedure LoadXmjLevel2(AXlsFile: TXLSFile; AParent: TBillsCacheNode);
-    procedure LoadXmjLevel3(AXlsFile: TXLSFile; AParent: TBillsCacheNode);
-    procedure LoadXmjLevel4(AXlsFile: TXLSFile; AParent: TBillsCacheNode);
-    procedure LoadXmjLevel5(AXlsFile: TXLSFile; AParent: TBillsCacheNode);
-    procedure LoadXmjLevel6(AXlsFile: TXLSFile; AParent: TBillsCacheNode);
-    procedure LoadXmjLevel7(AXlsFile: TXLSFile; AParent: TBillsCacheNode);
+    procedure LoadXmjLevel1(ASheet: TExportWorkSheet);
+    procedure LoadXmjLevel2(ASheet: TExportWorkSheet; AParent: TBillsCacheNode);
+    procedure LoadXmjLevel3(ASheet: TExportWorkSheet; AParent: TBillsCacheNode);
+    procedure LoadXmjLevel4(ASheet: TExportWorkSheet; AParent: TBillsCacheNode);
+    procedure LoadXmjLevel5(ASheet: TExportWorkSheet; AParent: TBillsCacheNode);
+    procedure LoadXmjLevel6(ASheet: TExportWorkSheet; AParent: TBillsCacheNode);
+    procedure LoadXmjLevel7(ASheet: TExportWorkSheet; AParent: TBillsCacheNode);
 
-    procedure LoadBillsNode(AXlsFile: TXLSFile; AXmj: TBillsCacheNode);
+    procedure LoadBillsNode(ASheet: TExportWorkSheet; AXmj: TBillsCacheNode);
 
-    function LoadColumnsFromHead(AXlsFile: TXlsFile): Boolean;
-    procedure LoadFxBills(AXlsFile: TXLSFile);
+    function LoadColumnsFromHead(ASheet: TExportWorkSheet): Boolean;
+    procedure LoadFxBills(ASheet: TExportWorkSheet);
 
     procedure WriteNode(ADataSet: TsdDataSet; ANode: TBillsCacheNode);
     procedure WriteNodes(ADataSet: TsdDataSet);
@@ -92,9 +91,9 @@ type
     procedure BeginImport; override;
     procedure EndImport; override;
 
-    procedure LoadColumnsFromHead;
+    procedure LoadColumnsFromHead(ASheet: TExportWorkSheet);
     procedure UpdateBillsPrice(const AB_Code: string; APrice: Double);
-    procedure ImportBillsPriceData;
+    procedure ImportBillsPriceData(ASheet: TExportWorkSheet);
     procedure Import; override;
   end;
 
@@ -109,105 +108,53 @@ uses
 constructor TDetailExcelImport.Create(AProjectData: TProjectData);
 begin
   FProjectData := AProjectData;
-  FTempFile := GetTempFileName;
+  FOExport := TOExport.Create;
+  FOExport.UseProgress := False;
 end;
 
 destructor TDetailExcelImport.Destroy;
 begin
-  if FileExists(FTempFile) then
-    DeleteFile(FTempFile);
+  FOExport.Free;
   inherited;
 end;
 
-function TDetailExcelImport.GetCellFloat(AXlsFile: TXLSFile; ARow,
+function TDetailExcelImport.GetCellFloat(ARow: TExportRow;
   ACol: Integer): Double;
 begin
-  Result := StrToFloatDef(GetCellTrimStr(AXlsFile, ARow, ACol), 0);
+  Result := StrToFloatDef(GetCellTrimStr(ARow, ACol), 0);
 end;
 
-function TDetailExcelImport.GetCellTrimStr(AXlsFile: TXLSFile; ARow,
+function TDetailExcelImport.GetCellStr(ARow: TExportRow;
   ACol: Integer): string;
 begin
-  Result := Trim(GetCellValue(AXlsFile, ARow, ACol));
+  if (ACol < ARow.Cells.Count) and (ACol >= 0) then
+    Result := ARow.Cells[ACol].SqlText
+  else
+    Result := '';
 end;
 
-function TDetailExcelImport.GetCellValue(AXlsFile: TXLSFile; ARow,
-  ACol: Integer): string;
-var
-  xlsCell: TXlsCellValue;
+function TDetailExcelImport.GetCellStr(ASheet: TExportWorkSheet; ARow, ACol: Integer): string;
 begin
-  Result := '';
-  if not Assigned(AXlsFile) or (ARow = -1) or (ACol = -1) then Exit;
-  xlsCell := AXlsFile.CellValueX[ARow, ACol];
-  Result := VarToStrDef(xlsCell.Value, '');
+  if ARow < ASheet.Rows.Count then
+    Result := GetCellStr(ASheet.Rows[ARow], ACol)
+  else
+    Result := '';
 end;
 
-function TDetailExcelImport.GetCellValueFormat(AXlsFile: TXLSFile; ARow,
+function TDetailExcelImport.GetCellTrimStr(ARow: TExportRow;
   ACol: Integer): string;
-
-  function GetDigit(AFormat: WideString): Integer;
-  var
-    I: Integer;
-    bDigit: Boolean;
-  begin
-    Result := 0;
-    bDigit := False;
-    for I := 1 to Length(AFormat) do
-    begin
-      if AFormat[I] = '.' then
-      begin
-        if bDigit then Break
-        else bDigit := True;
-      end
-      else if AFormat[I] = ';' then Break
-      else if bDigit and (AFormat[I] = '0') then
-        Dec(Result);
-    end;
-  end;
-
-  function FormatNum(AValue: Variant; AFormat: WideString): string;
-  begin
-    Result := AValue;
-    if not VarIsNull(AValue) then
-    begin
-      if CheckNumeric(Result) then
-      begin
-        if Pos('%', AFormat) <> 0 then AValue := AValue * 100;
-        if AFormat <> '' then
-          Result := FloatToStr(AdvRoundTo(AValue, GetDigit(AFormat)))
-        else
-          Result := FloatToStr(AdvRoundTo(AValue, -2));
-        if Pos('%', AFormat) <> 0 then Result := Result + '%';
-        if AValue = '0' then Result := '';
-      end;
-    end;
-  end;
-
-var
-  xlsCell: TXlsCellValue;
-  FlxFormat: TFlxFormat;
 begin
-  Result := '';
-  if not Assigned(AXlsFile) or (ARow = -1) or (ACol = -1) then Exit;
-  xlsCell := AXlsFile.GetCellDataX(ARow, ACol);
-  Result := xlsCell.Value;
-  if xlsCell.XF <> -1 then
-  begin
-    FlxFormat := AXlsFile.FormatList[xlsCell.XF];
-    Result := FormatNum(xlsCell.Value, FlxFormat.Format);
-  end;
+  Result := Trim(GetCellStr(ARow, ACol));
 end;
 
 procedure TDetailExcelImport.ImportFile(const AFileName: string);
 begin
-  CopyFileOrFolder(AFileName, FTempFile);
-  FExcel := TXlsOutPut.Create(FTempFile);
   BeginImport;
   try
+    FOExport.LoadFromFile(AFileName);
     Import;
   finally
     EndImport;
-    FExcel.Free;
   end;
 end;
 
@@ -215,27 +162,29 @@ end;
 
 procedure TPlaneFxBillsExcelImport.Import;
 begin
-  FCurRow := 1;
-  if LoadColumnsFromHead(FExcel.XlsFile) then
+  FCurRow := 0;
+  if LoadColumnsFromHead(FOExport.OpenWorkSheet) then
   begin
-    LoadFxBills(FExcel.XlsFile);
+    LoadFxBills(FOExport.OpenWorkSheet);
     WriteNodes(FProjectData.BillsData.sddBills);
   end
   else
     ErrorMessage('导入的Excel格式有误!');
 end;
 
-procedure TPlaneFxBillsExcelImport.LoadBillsNode(AXlsFile: TXLSFile;
+procedure TPlaneFxBillsExcelImport.LoadBillsNode(ASheet: TExportWorkSheet;
   AXmj: TBillsCacheNode);
 var
+  vRow: TExportRow;
   sB_Code, sName, sUnits: string;
   vGclNode: TBillsCacheNode;
   fPrice: Double;
 begin
-  sB_Code := Trim(GetCellValue(AXlsFile, FCurRow, FB_CodeCol));
-  sName := Trim(GetCellValue(AXlsFile, FCurRow, FNameCol));
-  sUnits := Trim(GetCellValue(AXlsFile, FCurRow, FUnitCol));
-  fPrice := StrToFloatDef(GetCellValue(AXlsFile, FCurRow, FPriceCol), 0);
+  vRow := ASheet.Rows[FCurRow];
+  sB_Code := Trim(GetCellStr(vRow, FB_CodeCol));
+  sName := Trim(GetCellStr(vRow, FNameCol));
+  sUnits := Trim(GetCellStr(vRow, FUnitCol));
+  fPrice := StrToFloatDef(GetCellStr(vRow, FPriceCol), 0);
   if sB_Code <> '' then
   begin
     vGclNode := FCacheTree.FindGclChild(AXmj, sB_Code, sName, sUnits, fPrice);
@@ -245,20 +194,21 @@ begin
       vGclNode.B_Code := sB_Code;
       vGclNode.Name := sName;
       vGclNode.Units := sUnits;
-      vGclNode.OrgQuantity := StrToFloatDef(GetCellValue(AXlsFile, FCurRow, FQuantityCol), 0);
+      vGclNode.OrgQuantity := StrToFloatDef(GetCellStr(vRow, FQuantityCol), 0);
       vGclNode.Price := fPrice;
-      vGclNode.DrawingCode := Trim(GetCellValue(AXlsFile, FCurRow, FDrawingCol));
-      vGclNode.MemoStr := Trim(GetCellValue(AXlsFile, FCurRow, FMemoCol));
+      vGclNode.DrawingCode := Trim(GetCellStr(vRow, FDrawingCol));
+      vGclNode.MemoStr := Trim(GetCellStr(vRow, FMemoCol));
     end
     else
-      vGclNode.OrgQuantity := vGclNode.OrgQuantity + StrToFloatDef(GetCellValue(AXlsFile, FCurRow, FQuantityCol), 0);
+      vGclNode.OrgQuantity := vGclNode.OrgQuantity + StrToFloatDef(GetCellStr(vRow, FQuantityCol), 0);
   end;
   Inc(FCurRow);
 end;
 
-function TPlaneFxBillsExcelImport.LoadColumnsFromHead(AXlsFile: TXlsFile): Boolean;
+function TPlaneFxBillsExcelImport.LoadColumnsFromHead(ASheet: TExportWorkSheet): Boolean;
 var
   iCol: Integer;
+  vRow: TExportRow;
   sColName: string;
 begin
   Result := False;
@@ -279,11 +229,12 @@ begin
   UpdateProgressHint('正在识别Excel数据格式');
   UpdateProgressPosition(0);
 
-  while not Result and (FCurRow <= AXlsFile.MaxRow) do
+  while not Result and (FCurRow <= ASheet.Rows.Count - 1) do
   begin
-    for iCol := 1 to AXlsFile.MaxCol do
+    vRow := ASheet.Rows[FCurRow];
+    for iCol := 0 to vRow.Cells.Count - 1 do
     begin
-      sColName := Trim(GetCellValue(AXlsFile, FCurRow, iCol));
+      sColName := vRow.Cells[iCol].SqlText;
       if sColName = '第1层' then
         FXmjLevel1Col := iCol
       else if sColName = '第2层' then
@@ -319,273 +270,333 @@ begin
   end;
 end;
 
-procedure TPlaneFxBillsExcelImport.LoadFxBills(AXlsFile: TXLSFile);
+procedure TPlaneFxBillsExcelImport.LoadFxBills(ASheet: TExportWorkSheet);
 var
   iPos: Integer;
 begin
   UpdateProgressHint('正在解析平面台账数据');
-  while FCurRow <= AXlsFile.MaxRow do
+  while FCurRow < ASheet.Rows.Count do
   begin
-    iPos := FCurRow*100 div AXlsFile.MaxRow;
+    iPos := FCurRow * 100 div ASheet.Rows.Count;
     UpdateProgressPosition(iPos);
-    LoadXmjLevel1(AXlsFile);
+    LoadXmjLevel1(ASheet);
   end;
 end;
 
-procedure TPlaneFxBillsExcelImport.LoadXmjLevel1(AXlsFile: TXLSFile);
+procedure TPlaneFxBillsExcelImport.LoadXmjLevel1(ASheet: TExportWorkSheet);
 var
+  vRow: TExportRow;
+  vCell: TExportCell;
   sName: string;
   vXmj: TBillsCacheNode;
   iEndRow: Integer;
 begin
-  sName := Trim(GetCellValue(AXlsFile, FCurRow, FXmjLevel1Col));
-  with AXlsFile.CellMergedBounds[FCurRow, FXmjLevel1Col] do
-    iEndRow := FCurRow + Bottom - Top;
-
-  if sName <> '' then
+  vRow := ASheet.Rows[FCurRow];
+  if FXmjLevel1Col < vRow.Cells.Count then
   begin
-    vXmj := FCacheTree.FindXmjChild(nil, '', sName);
-    if not Assigned(vXmj) then
-    begin
-      vXmj := FCacheTree.AddNode(nil);
-      vXmj.Name := sName;
-    end;
+    vCell := vRow.Cells[FXmjLevel1Col];
 
-    if FXmjLevel2Col <> -1 then
+    sName := Trim(vCell.SqlText);
+    iEndRow := FCurRow + vCell.RowSpan;
+    if (sName <> '') then
     begin
-      while FCurRow <= iEndRow do
-        LoadXmjLevel2(AXlsFile, vXmj);
+      vXmj := FCacheTree.FindXmjChild(nil, '', sName);
+      if not Assigned(vXmj) then
+      begin
+        vXmj := FCacheTree.AddNode(nil);
+        vXmj.Name := sName;
+      end;
+
+      if FXmjLevel2Col <> -1 then
+      begin
+        while FCurRow < iEndRow do
+          LoadXmjLevel2(ASheet, vXmj);
+      end
+      else
+      begin
+        while FCurRow < iEndRow do
+          LoadBillsNode(ASheet, vXmj);
+      end;
     end
     else
-    begin
-      while FCurRow <= iEndRow do
-        LoadBillsNode(AXlsFile, vXmj);
-    end;
+      Inc(FCurRow);
   end
   else
     Inc(FCurRow);
 end;
 
-procedure TPlaneFxBillsExcelImport.LoadXmjLevel2(AXlsFile: TXLSFile;
+procedure TPlaneFxBillsExcelImport.LoadXmjLevel2(ASheet: TExportWorkSheet;
   AParent: TBillsCacheNode);
 var
+  vRow: TExportRow;
+  vCell: TExportCell;
   sName: string;
   vXmj: TBillsCacheNode;
   iEndRow: Integer;
 begin
-  sName := Trim(GetCellValue(AXlsFile, FCurRow, FXmjLevel2Col));
-  with AXlsFile.CellMergedBounds[FCurRow, FXmjLevel2Col] do
-    iEndRow := FCurRow + Bottom - Top;
-
-  if sName <> '' then
+  vRow := ASheet.Rows[FCurRow];
+  if FXmjLevel2Col < vRow.Cells.Count then
   begin
-    vXmj := FCacheTree.FindXmjChild(AParent, '', sName);
-    if not Assigned(vXmj) then
-    begin
-      vXmj := FCacheTree.AddNode(AParent);
-      vXmj.Name := sName;
-    end;
+    vCell := vRow.Cells[FXmjLevel2Col];
 
+    sName := Trim(vCell.SqlText);
+    iEndRow := FCurRow + vCell.RowSpan;
 
-    if FXmjLevel3Col <> -1 then
+    if (sName <> '') then
     begin
-      while FCurRow <= iEndRow do
-        LoadXmjLevel3(AXlsFile, vXmj);
+      vXmj := FCacheTree.FindXmjChild(AParent, '', sName);
+      if not Assigned(vXmj) then
+      begin
+        vXmj := FCacheTree.AddNode(AParent);
+        vXmj.Name := sName;
+      end;
+
+      if FXmjLevel3Col <> -1 then
+      begin
+        while FCurRow < iEndRow do
+          LoadXmjLevel3(ASheet, vXmj);
+      end
+      else
+      begin
+        while FCurRow < iEndRow do
+          LoadBillsNode(ASheet, vXmj);
+      end;
     end
     else
     begin
-      while FCurRow <= iEndRow do
-        LoadBillsNode(AXlsFile, vXmj);
+      while FCurRow < iEndRow do
+        LoadBillsNode(ASheet, AParent);
     end;
   end
   else
-  begin
-    while FCurRow <= iEndRow do
-      LoadBillsNode(AXlsFile, AParent);
-  end;
+    Inc(FCurRow);
 end;
 
-procedure TPlaneFxBillsExcelImport.LoadXmjLevel3(AXlsFile: TXLSFile;
+procedure TPlaneFxBillsExcelImport.LoadXmjLevel3(ASheet: TExportWorkSheet;
   AParent: TBillsCacheNode);
 var
+  vRow: TExportRow;
+  vCell: TExportCell;
   sName: string;
   vXmj: TBillsCacheNode;
   iEndRow: Integer;
 begin
-  sName := Trim(GetCellValue(AXlsFile, FCurRow, FXmjLevel3Col));
-  with AXlsFile.CellMergedBounds[FCurRow, FXmjLevel3Col] do
-    iEndRow := FCurRow + Bottom - Top;
-
-  if sName <> '' then
+  vRow := ASheet.Rows[FCurRow];
+  if FXmjLevel3Col < vRow.Cells.Count then
   begin
-    vXmj := FCacheTree.FindXmjChild(AParent, '', sName);
-    if not Assigned(vXmj) then
-    begin
-      vXmj := FCacheTree.AddNode(AParent);
-      vXmj.Name := sName;
-    end;
+    vCell := vRow.Cells[FXmjLevel3Col];
+
+    sName := Trim(vCell.SqlText);
+    iEndRow := FCurRow + vCell.RowSpan;
 
-    if FXmjLevel4Col <> -1 then
+    if (sName <> '') then
     begin
-      while FCurRow <= iEndRow do
-        LoadXmjLevel4(AXlsFile, vXmj);
+      vXmj := FCacheTree.FindXmjChild(AParent, '', sName);
+      if not Assigned(vXmj) then
+      begin
+        vXmj := FCacheTree.AddNode(AParent);
+        vXmj.Name := sName;
+      end;
+
+      if FXmjLevel4Col <> -1 then
+      begin
+        while FCurRow < iEndRow do
+          LoadXmjLevel4(ASheet, vXmj);
+      end
+      else
+      begin
+        while FCurRow < iEndRow do
+          LoadBillsNode(ASheet, vXmj);
+      end;
     end
     else
     begin
-      while FCurRow <= iEndRow do
-        LoadBillsNode(AXlsFile, vXmj);
+      while FCurRow < iEndRow do
+        LoadBillsNode(ASheet, AParent);
     end;
   end
   else
-  begin
-    while FCurRow <= iEndRow do
-      LoadBillsNode(AXlsFile, AParent);
-  end;
+    Inc(FCurRow);
 end;
 
-procedure TPlaneFxBillsExcelImport.LoadXmjLevel4(AXlsFile: TXLSFile;
+procedure TPlaneFxBillsExcelImport.LoadXmjLevel4(ASheet: TExportWorkSheet;
   AParent: TBillsCacheNode);
 var
+  vRow: TExportRow;
+  vCell: TExportCell;
   sName: string;
   vXmj: TBillsCacheNode;
   iEndRow: Integer;
 begin
-  sName := Trim(GetCellValue(AXlsFile, FCurRow, FXmjLevel4Col));
-  with AXlsFile.CellMergedBounds[FCurRow, FXmjLevel4Col] do
-    iEndRow := FCurRow + Bottom - Top;
-
-  if sName <> '' then
+  vRow := ASheet.Rows[FCurRow];
+  if FXmjLevel4Col < vRow.Cells.Count then
   begin
-    vXmj := FCacheTree.FindXmjChild(AParent, '', sName);
-    if not Assigned(vXmj) then
-    begin
-      vXmj := FCacheTree.AddNode(AParent);
-      vXmj.Name := sName;
-    end;
+    vCell := vRow.Cells[FXmjLevel4Col];
+
+    sName := Trim(vCell.SqlText);
+    iEndRow := FCurRow + vCell.RowSpan;
 
-    if FXmjLevel5Col <> -1 then
+    if (sName <> '') then
     begin
-      while FCurRow <= iEndRow do
-        LoadXmjLevel5(AXlsFile, vXmj);
+      vXmj := FCacheTree.FindXmjChild(AParent, '', sName);
+      if not Assigned(vXmj) then
+      begin
+        vXmj := FCacheTree.AddNode(AParent);
+        vXmj.Name := sName;
+      end;
+
+      if FXmjLevel5Col <> -1 then
+      begin
+        while FCurRow < iEndRow do
+          LoadXmjLevel5(ASheet, vXmj);
+      end
+      else
+      begin
+        while FCurRow < iEndRow do
+          LoadBillsNode(ASheet, vXmj);
+      end;
     end
     else
     begin
-      while FCurRow <= iEndRow do
-        LoadBillsNode(AXlsFile, vXmj);
+      while FCurRow < iEndRow do
+        LoadBillsNode(ASheet, AParent);
     end;
   end
   else
-  begin
-    while FCurRow <= iEndRow do
-      LoadBillsNode(AXlsFile, AParent);
-  end;
+    Inc(FCurRow);
 end;
 
-procedure TPlaneFxBillsExcelImport.LoadXmjLevel5(AXlsFile: TXLSFile;
+procedure TPlaneFxBillsExcelImport.LoadXmjLevel5(ASheet: TExportWorkSheet;
   AParent: TBillsCacheNode);
 var
+  vRow: TExportRow;
+  vCell: TExportCell;
   sName: string;
   vXmj: TBillsCacheNode;
   iEndRow: Integer;
 begin
-  sName := Trim(GetCellValue(AXlsFile, FCurRow, FXmjLevel5Col));
-  with AXlsFile.CellMergedBounds[FCurRow, FXmjLevel5Col] do
-    iEndRow := FCurRow + Bottom - Top;
-
-  if sName <> '' then
+  vRow := ASheet.Rows[FCurRow];
+  if FXmjLevel5Col < vRow.Cells.Count then
   begin
-    vXmj := FCacheTree.FindXmjChild(AParent, '', sName);
-    if not Assigned(vXmj) then
-    begin
-      vXmj := FCacheTree.AddNode(AParent);
-      vXmj.Name := sName;
-    end;
+    vCell := vRow.Cells[FXmjLevel5Col];
 
-    if FXmjLevel6Col <> -1 then
+    sName := Trim(vCell.SqlText);
+    iEndRow := FCurRow + vCell.RowSpan;
+
+    if (sName <> '') then
     begin
-      while FCurRow <= iEndRow do
-        LoadXmjLevel6(AXlsFile, vXmj);
+      vXmj := FCacheTree.FindXmjChild(AParent, '', sName);
+      if not Assigned(vXmj) then
+      begin
+        vXmj := FCacheTree.AddNode(AParent);
+        vXmj.Name := sName;
+      end;
+
+      if FXmjLevel6Col <> -1 then
+      begin
+        while FCurRow < iEndRow do
+          LoadXmjLevel6(ASheet, vXmj);
+      end
+      else
+      begin
+        while FCurRow < iEndRow do
+          LoadBillsNode(ASheet, vXmj);
+      end;
     end
     else
     begin
-      while FCurRow <= iEndRow do
-        LoadBillsNode(AXlsFile, vXmj);
+      while FCurRow < iEndRow do
+        LoadBillsNode(ASheet, AParent);
     end;
   end
   else
-  begin
-    while FCurRow <= iEndRow do
-      LoadBillsNode(AXlsFile, AParent);
-  end;
+    Inc(FCurRow);
 end;
 
-procedure TPlaneFxBillsExcelImport.LoadXmjLevel6(AXlsFile: TXLSFile;
+procedure TPlaneFxBillsExcelImport.LoadXmjLevel6(ASheet: TExportWorkSheet;
   AParent: TBillsCacheNode);
 var
+  vRow: TExportRow;
+  vCell: TExportCell;
   sName: string;
   vXmj: TBillsCacheNode;
   iEndRow: Integer;
 begin
-  sName := Trim(GetCellValue(AXlsFile, FCurRow, FXmjLevel6Col));
+  vRow := ASheet.Rows[FCurRow];
+  if FXmjLevel6Col < vRow.Cells.Count then
+  begin
+    vCell := vRow.Cells[FXmjLevel6Col];
 
-  with AXlsFile.CellMergedBounds[FCurRow, FXmjLevel6Col] do
-    iEndRow := FCurRow + Bottom - Top;
+    sName := Trim(vCell.SqlText);
+    iEndRow := FCurRow + vCell.RowSpan;
 
-  if sName <> '' then
-  begin
-    vXmj := FCacheTree.FindXmjChild(AParent, '', sName);
-    if not Assigned(vXmj) then
+    if (sName <> '') then
     begin
-      vXmj := FCacheTree.AddNode(AParent);
-      vXmj.Name := sName;
-    end;
+      vXmj := FCacheTree.FindXmjChild(AParent, '', sName);
+      if not Assigned(vXmj) then
+      begin
+        vXmj := FCacheTree.AddNode(AParent);
+        vXmj.Name := sName;
+      end;
 
-    if FXmjLevel7Col <> -1 then
-    begin
-      while FCurRow <= iEndRow do
-        LoadXmjLevel7(AXlsFile, vXmj);
+      if FXmjLevel7Col <> -1 then
+      begin
+        while FCurRow < iEndRow do
+          LoadXmjLevel7(ASheet, vXmj);
+      end
+      else
+      begin
+        while FCurRow < iEndRow do
+          LoadBillsNode(ASheet, vXmj);
+      end;
     end
     else
     begin
-      while FCurRow <= iEndRow do
-        LoadBillsNode(AXlsFile, vXmj);
+      while FCurRow < iEndRow do
+        LoadBillsNode(ASheet, AParent);
     end;
   end
   else
-  begin
-    while FCurRow <= iEndRow do
-      LoadBillsNode(AXlsFile, AParent);
-  end;
+    Inc(FCurRow);
 end;
 
-procedure TPlaneFxBillsExcelImport.LoadXmjLevel7(AXlsFile: TXLSFile;
+procedure TPlaneFxBillsExcelImport.LoadXmjLevel7(ASheet: TExportWorkSheet;
   AParent: TBillsCacheNode);
 var
+  vRow: TExportRow;
+  vCell: TExportCell;
   sName: string;
   vXmj: TBillsCacheNode;
   iEndRow: Integer;
 begin
-  sName := Trim(GetCellValue(AXlsFile, FCurRow, FXmjLevel7Col));
-  if sName <> '' then
+  vRow := ASheet.Rows[FCurRow];
+  if FXmjLevel7Col < vRow.Cells.Count then
   begin
-    vXmj := FCacheTree.FindXmjChild(AParent, '', sName);
-    if not Assigned(vXmj) then
-    begin
-      vXmj := FCacheTree.AddNode(AParent);
-      vXmj.Name := sName;
-    end;
+    vCell := vRow.Cells[FXmjLevel7Col];
+
+    sName := Trim(vCell.SqlText);
+    iEndRow := FCurRow + vCell.RowSpan;
 
-    with AXlsFile.CellMergedBounds[FCurRow, FXmjLevel7Col] do
-      iEndRow := FCurRow + Bottom - Top;
+    if (sName <> '') then
+    begin
+      vXmj := FCacheTree.FindXmjChild(AParent, '', sName);
+      if not Assigned(vXmj) then
+      begin
+        vXmj := FCacheTree.AddNode(AParent);
+        vXmj.Name := sName;
+      end;
 
-    while FCurRow <= iEndRow do
-      LoadBillsNode(AXlsFile, vXmj);
+      while FCurRow < iEndRow do
+        LoadBillsNode(ASheet, vXmj);
+    end
+    else
+    begin
+      while FCurRow < iEndRow do
+        LoadBillsNode(ASheet, AParent);
+    end;
   end
   else
-  begin
-    while FCurRow <= iEndRow do
-      LoadBillsNode(AXlsFile, AParent);  
-  end;
+    Inc(FCurRow);
 end;
 
 procedure TPlaneFxBillsExcelImport.WriteNodes(ADataSet: TsdDataSet);
@@ -668,7 +679,7 @@ procedure TBillsPriceExcelImport.BeginImport;
 begin
   ShowProgressHint('导入Excel清单单价', 100);
   FProjectData.BillsData.sddBills.BeginUpdate;
-  FCurRow := 1;
+  FCurRow := 0;
 end;
 
 procedure TBillsPriceExcelImport.EndImport;
@@ -680,12 +691,15 @@ begin
 end;
 
 procedure TBillsPriceExcelImport.Import;
+var
+  vSheet: TExportWorkSheet;
 begin
-  LoadColumnsFromHead;
-  ImportBillsPriceData;
+  vSheet := OExport.OpenWorkSheet;
+  LoadColumnsFromHead(vSheet);
+  ImportBillsPriceData(vSheet);
 end;
 
-procedure TBillsPriceExcelImport.ImportBillsPriceData;
+procedure TBillsPriceExcelImport.ImportBillsPriceData(ASheet: TExportWorkSheet);
 
   function CheckIsBillsCode(ACode: string): Boolean;
   const
@@ -706,40 +720,44 @@ procedure TBillsPriceExcelImport.ImportBillsPriceData;
   end;
 
 var
+  vRow: TExportRow;
   iPos: Integer;
   sB_Code: string;
   fPrice: Double;
 begin
   UpdateProgressHint('写入读取的Excel数据');
   UpdateProgressPosition(0);
-  while (FCurRow <= Excel.XlsFile.MaxRow) do
+  while (FCurRow < ASheet.Rows.Count) do
   begin
-    sB_Code := GetCellTrimStr(Excel.XlsFile, FCurRow, FB_CodeCol);
+    vRow := ASheet.Rows[FCurRow];
+    sB_Code := Trim(GetCellStr(vRow, FB_CodeCol));
     if (sB_Code <> '') and CheckIsBillsCode(sB_Code) then
     begin
-      fPrice := GetCellFloat(Excel.XlsFile, FCurRow, FPriceCol);
+      fPrice := StrToFloatDef(Trim(GetCellStr(vRow, FPriceCol)), 0);
       UpdateBillsPrice(sB_Code, fPrice);
     end;
     Inc(FCurRow);
-    iPos := FCurRow * 100 div Excel.XlsFile.MaxRow;
+    iPos := (FCurRow + 1) * 100 div ASheet.Rows.Count;
     UpdateProgressPosition(iPos);
   end;
   UpdateProgressPosition(100);
 end;
 
-procedure TBillsPriceExcelImport.LoadColumnsFromHead;
+procedure TBillsPriceExcelImport.LoadColumnsFromHead(ASheet: TExportWorkSheet);
 var
+  vRow: TExportRow;
   iCol: Integer;
   sColName: string;
 begin
   FB_CodeCol := -1;
   FNameCol := -1;
   FPriceCol := -1;
-  while ((FB_CodeCol = -1) or (FPriceCol = -1)) and (FCurRow <= Excel.XlsFile.MaxRow) do
+  while ((FB_CodeCol = -1) or (FPriceCol = -1)) and (FCurRow < ASheet.Rows.Count) do
   begin
-    for iCol := 1 to Excel.XlsFile.MaxCol do
+    vRow := ASheet.Rows[FCurRow];
+    for iCol := 0 to vRow.Cells.Count - 1 do
     begin
-      sColName := GetCellTrimStr(Excel.XlsFile, FCurRow, iCol);
+      sColName := Trim(GetCellStr(vRow, iCol));
       if SameText(sColName, '清单编号') or SameText(sColName, '子目号') then
         FB_CodeCol := iCol
       else if SameText(sColName, '名称') then

+ 30 - 28
Units/ExcelImport_Bills.pas

@@ -5,7 +5,7 @@ unit ExcelImport_Bills;
 interface
 
 uses
-  DetailExcelImport, Classes, MCacheTree, sdDB, ProjectData;
+  DetailExcelImport, Classes, MCacheTree, sdDB, ProjectData, OExport;
 
 type
   Tdei_CustomBills = class(TDetailExcelImport)
@@ -42,12 +42,12 @@ type
 
     procedure CheckFixedIDNodes;
 
-    procedure LoadColumnsFromHead;
+    procedure LoadColumnsFromHead(ASheet: TExportWorkSheet);
 
     procedure LoadBaseTree(ATree: TBillsCacheTree);
 
-    procedure LoadNode;
-    procedure LoadNodes;
+    procedure LoadNode(ARow: TExportRow);
+    procedure LoadNodes(ASheet: TExportWorkSheet);
 
     procedure WriteNode(ADataSet: TsdDataSet; ANode: TBillsCacheNode);
     procedure WriteNodes(ADataSet: TsdDataSet);
@@ -70,7 +70,7 @@ begin
   Screen.Cursor := crHourGlass;
   ShowProgressHint('导入Excel数据', 100, '读取Excel数据', 100);
 
-  FCurRow := 1;
+  FCurRow := 0;
   FIsFirstPart := True;
   FCacheTree := TBillsCacheTree.Create;
   FCacheTree.NewNodeID := 101;
@@ -204,8 +204,8 @@ begin
     LoadBaseTree(FBaseTree)
   else
     LoadBaseTree(FCacheTree);
-  LoadColumnsFromHead;
-  LoadNodes;
+  LoadColumnsFromHead(OExport.OpenWorkSheet);
+  LoadNodes(OExport.OpenWorkSheet);
   WriteNodes(ProjectData.BillsData.sddBills);
 end;
 
@@ -229,8 +229,9 @@ begin
   end;
 end;
 
-procedure Tdei_CustomBills.LoadColumnsFromHead;
+procedure Tdei_CustomBills.LoadColumnsFromHead(ASheet: TExportWorkSheet);
 var
+  vRow: TExportRow;
   iCol: Integer;
   sColName: string;
 begin
@@ -248,9 +249,10 @@ begin
   FMemoCol := -1;
   FLevelCol := -1;
 
-  for iCol := 1 to Excel.XlsFile.MaxCol do
+  vRow := ASheet.Rows[FCurRow];
+  for iCol := 0 to vRow.Cells.Count - 1 do
   begin
-    sColName := GetCellTrimStr(Excel.XlsFile, FCurRow, iCol);
+    sColName := GetCellTrimStr(vRow, iCol);
 
     if Pos('项目节', sColName) > 0 then
       FCodeCol := iCol
@@ -282,17 +284,17 @@ begin
   Inc(FCurRow);
 end;
 
-procedure Tdei_CustomBills.LoadNode;
+procedure Tdei_CustomBills.LoadNode(ARow: TExportRow);
 var
   sLevelCode, sCode, sB_Code, sName: string;
   Node: TBillsCacheNode;
   vValue: Variant;
   iFixedID: Integer;
 begin
-  sLevelCode := GetCellTrimStr(Excel.XlsFile, FCurRow, FLevelCol);
-  sCode := GetCellTrimStr(Excel.XlsFile, FCurRow, FCodeCol);
-  sB_Code := GetCellTrimStr(Excel.XlsFile, FCurRow, FB_CodeCol);
-  sName := GetCellTrimStr(Excel.XlsFile, FCurRow, FNameCol);
+  sLevelCode := GetCellTrimStr(ARow, FLevelCol);
+  sCode := GetCellTrimStr(ARow, FCodeCol);
+  sB_Code := GetCellTrimStr(ARow, FB_CodeCol);
+  sName := GetCellTrimStr(ARow, FNameCol);
 
   // 含层次编号时,层次编号为空不导入
   // 不含层次编号时,仅导入第一部分,且项目节编号、清单编号均未空时不导入
@@ -339,26 +341,26 @@ begin
   Node.Code := sCode;
   Node.B_Code := sB_Code;
   Node.Name := sName;
-  Node.Units := GetCellTrimStr(Excel.XlsFile, FCurRow, FUnitsCol);
-  Node.Price := GetCellFloat(Excel.XlsFile, FCurRow, FPriceCol);
-  Node.OrgQuantity := GetCellFloat(Excel.XlsFile, FCurRow, FOrgQuantityCol);
-  Node.MisQuantity := GetCellFloat(Excel.XlsFile, FCurRow, FMisQuantityCol);
-  Node.OthQuantity := GetCellFloat(Excel.XlsFile, FCurRow, FOthQuantityCol);
-  Node.DgnQuantity1 := GetCellFloat(Excel.XlsFile, FCurRow, FDgnQuantity1Col);
-  Node.DgnQuantity2 := GetCellFloat(Excel.XlsFile, FCurRow, FDgnQuantity2Col);
-  Node.DrawingCode := GetCellTrimStr(Excel.XlsFile, FCurRow, FDrawingCol);
-  Node.MemoStr := GetCellTrimStr(Excel.XlsFile, FCurRow, FMemoCol);
+  Node.Units := GetCellTrimStr(ARow, FUnitsCol);
+  Node.Price := GetCellFloat(ARow, FPriceCol);
+  Node.OrgQuantity := GetCellFloat(ARow, FOrgQuantityCol);
+  Node.MisQuantity := GetCellFloat(ARow, FMisQuantityCol);
+  Node.OthQuantity := GetCellFloat(ARow, FOthQuantityCol);
+  Node.DgnQuantity1 := GetCellFloat(ARow, FDgnQuantity1Col);
+  Node.DgnQuantity2 := GetCellFloat(ARow, FDgnQuantity2Col);
+  Node.DrawingCode := GetCellTrimStr(ARow, FDrawingCol);
+  Node.MemoStr := GetCellTrimStr(ARow, FMemoCol);
 end;
 
-procedure Tdei_CustomBills.LoadNodes;
+procedure Tdei_CustomBills.LoadNodes(ASheet: TExportWorkSheet);
 var
   iPos, iSubPos: Integer;
 begin
-  while (FCurRow <= Excel.XlsFile.MaxRow){ and FIsFirstPart }do
+  while (FCurRow < ASheet.Rows.Count){ and FIsFirstPart }do
   begin
-    LoadNode;
+    LoadNode(ASheet.Rows[FCurRow]);
     Inc(FCurRow);
-    iSubPos := FCurRow * 100 div Excel.XlsFile.MaxRow;
+    iSubPos := (FCurRow + 1) * 100 div ASheet.Rows.Count;
     iPos := iSubPos div 2;
     UpdateProgressPosition(iPos, iSubPos);
   end;

+ 20 - 20
Units/ExcelImport_GclBills.pas

@@ -4,7 +4,7 @@ unit ExcelImport_GclBills;
 interface
 
 uses
-  Classes, DetailExcelImport, MCacheTree, sdDB;
+  Classes, DetailExcelImport, MCacheTree, sdDB, OExport;
 
 type
   TDEI_GclBills = class(TDetailExcelImport)
@@ -25,7 +25,7 @@ type
 
     procedure Import; override;
 
-    procedure ImportSheet;
+    procedure ImportSheet(ASheet: TExportWorkSheet);
 
     procedure WriteNode(ADataSet: TsdDataSet; ANode: TGclCacheNode);
     procedure WriteNodes(ADataSet: TsdDataSet);
@@ -36,7 +36,7 @@ type
 implementation
 
 uses
-  Forms, mDataRecord, Controls, ProgressHintFrm, UtilMethods;
+  Forms, mDataRecord, Controls, ProgressHintFrm, UtilMethods, SysUtils;
 
 { TDEI_GclBills }
 
@@ -53,11 +53,11 @@ begin
 
   FSelectSheets := TList.Create;
 
-  FB_CodeCol := 1;
-  FNameCol := 2;
-  FUnitsCol := 3;
-  FQuantityCol := 4;
-  FPriceCol :=  5;
+  FB_CodeCol := 0;
+  FNameCol := 1;
+  FUnitsCol := 2;
+  FQuantityCol := 3;
+  FPriceCol :=  4;
 end;
 
 procedure TDEI_GclBills.EndImport;
@@ -93,34 +93,34 @@ begin
       ImportSheet(FSelectSheets.Items[i]);
     end;
   end;}
-  ImportSheet;
+  ImportSheet(OExport.OpenWorkSheet);
   WriteNodes(ProjectData.BillsData.sddBills);
 end;
 
-procedure TDEI_GclBills.ImportSheet;
+procedure TDEI_GclBills.ImportSheet(ASheet: TExportWorkSheet);
 var
-  iPos: Integer; 
+  vRow: TExportRow;
+  iPos, iRow: Integer;
   sB_Code, sName: string;
   Node: TGclCacheNode;
 begin
-  FCurRow := 2;
-  while (FCurRow <= Excel.XlsFile.MaxRow) do
+  for iRow := 1 to ASheet.Rows.Count do
   begin
-    sB_Code := GetCellTrimStr(Excel.XlsFile, FCurRow, FB_CodeCol);
-    sName := GetCellTrimStr(Excel.XlsFile, FCurRow, FNameCol);
+    vRow := ASheet.Rows[iRow];
+    sB_Code := GetCellTrimStr(vRow, FB_CodeCol);
+    sName := GetCellTrimStr(vRow, FNameCol);
 
     if (sB_Code <> '') or (sName <> '') then
     begin
       Node := FCacheTree.AddNodeByData(sB_Code, sName);
       Node.B_Code := sB_Code;
       Node.Name := sName;
-      Node.Units := GetCellTrimStr(Excel.XlsFile, FCurRow, FUnitsCol);
-      Node.Price := GetCellFloat(Excel.XlsFile, FCurRow, FPriceCol);
-      Node.Quantity := GetCellFloat(Excel.XlsFile, FCurRow, FQuantityCol);
+      Node.Units := GetCellTrimStr(vRow, FUnitsCol);
+      Node.Price := GetCellFloat(vRow, FPriceCol);
+      Node.Quantity := GetCellFloat(vRow, FQuantityCol);
     end;
 
-    Inc(FCurRow);
-    iPos := FCurRow * 100 div Excel.XlsFile.MaxRow;
+    iPos := (iRow + 1) * 100 div ASheet.Rows.Count;
     UpdateProgressPosition(iPos);
   end;
 end;

+ 21 - 7
Units/UtilMethods.pas

@@ -50,6 +50,7 @@ type
   function SelectFile(var AFileName: string; const AExt: string): Boolean;
   function SelectFiles(AFiles: TStrings; const AExt: string): Boolean;
   function SaveFile(var FileName: string; const AExt: string): Boolean;
+  function SelectExcelFile(var AFileName: string): Boolean;
   function SaveExcelFile(var FileName: string): Boolean;
   function SelectOutputDirectory(const ATitle: string; var ADirectory: string;
     AParentHandle: THandle = 0; AHasNewFolderBtn: Boolean = True): Boolean;
@@ -448,6 +449,26 @@ begin
   end;
 end;
 
+function SelectExcelFile(var AFileName: string): Boolean;
+var
+  odFile: TOpenDialog;
+begin
+  odFile := TOpenDialog.Create(nil);
+  try
+    odFile.Filter := 'ExcelÎļþ(*.xls)|*.xls;|ExcelÎļþ(*.xlsx)|*.xlsx;';
+    if odFile.Execute then
+    begin
+      Application.ProcessMessages;
+      AFileName := odFile.FileName;
+      Result := True;
+    end
+    else
+      Result := False;
+  finally
+    odFile.Free;
+  end;
+end;
+
 function SaveExcelFile(var FileName: string): Boolean;
 
   function CheckFileName(AFileName: string; AExt: string): string;
@@ -473,13 +494,6 @@ begin
         2: FileName := CheckFileName(sdFile.FileName, '.xlsx');
       end;
     end;
-    (*
-      if sdFile.FilterIndex = 1 then
-      if not SameText(ExtractFileExt(sdFile.FileName), sdFile.DefaultExt) then
-        FileName := ExtractFileName(sdFile.FileName) + sdFile.DefaultExt
-      else
-        FileName := sdFile.FileName;
-    *)
   finally
     sdFile.Free;
   end;