我需要做的是从 excel 文件中读取表格详细信息,并希望从中创建 .pas 文件。
出于读写目的,我在 delphi 7 中使用了记录类型。
以下是我迄今为止尝试过的代码:
unit fImportFile;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Label1: TLabel;
tSourceFile: TEdit;
dlgSourceFile: TOpenDialog;
btnImport: TButton;
procedure tSourceFileClick(Sender: TObject);
procedure btnImportClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TTableDetails = record
fTableName: String;
end;
TFieldDetails = record
fFieldName: String;
fType: String;
fShortAlias: String;
fLongAlias: String;
fDomainName: String;
fFieldAttributes:TStringList;
fComments: String;
end;
var
Form1: TForm1;
implementation
uses ComObj, uFileGeneration;
{$R *.dfm}
procedure TForm1.tSourceFileClick(Sender: TObject);
begin
with dlgSourceFile do
begin
FileName := tSourceFile.Text;
if ExtractFilePath(FileName) <> '' then
InitialDir := ExtractFilePath(FileName);
if Execute then
if FileName <> '' then
tSourceFile.Text := FileName;
end;
end;
procedure TForm1.btnImportClick(Sender: TObject);
const
cEndOfTables = '';
cTable = 'Table';
cTableCell = 2;
cTableNameCell = 3; // TableNameField
cFieldName = 'Field Name';
var
Excel: OleVariant;
iRow: Integer;
aTableDetails: TTableDetails;
aFieldDetails: Array of TFieldDetails;
fieldCount: Integer;
iTableName, FldWithChar, FldWithoutChar: String;
FldList, WordList: TStringList;
FieldName: String;
begin
FldList := nil;
WordList := nil;
try
Excel := CreateOleObject('Excel.Application');
Excel.Visible := False;
Excel.Workbooks.Open(tSourceFile.Text);
iRow := 1;
while (Excel.ActiveSheet.Cells[iRow,cTableCell].Value <> '') do //To exit loop when the excel record will read blank TableName
begin
if (Excel.ActiveSheet.Cells[iRow,cTableCell].Value = cTable) then
begin
iTableName := Excel.ActiveSheet.Cells[iRow,cTableNameCell].Value;
if (iTableName = '') then
begin
ShowMessage('Table Name cannot be blank.');
exit;
end;
aTableDetails.fTableName := iTableName;
Inc(iRow);
fieldCount := 0;
FldList := TStringList.Create;
WordList := TStringList.Create;
ShowMessage('1 -- iRow --> ' + IntToStr(iRow));
while (Excel.ActiveSheet.Cells[iRow,cTableCell].Value <> '') AND
(Excel.ActiveSheet.Cells[iRow,cTableCell].Value <> cTable) do //Will create record until another table will found
begin
ShowMessage('2 -- Excel.ActiveSheet.Cells[iRow,cTableNameCell].Value = ' + Excel.ActiveSheet.Cells[iRow,cTableNameCell].Value);
FieldName := Excel.ActiveSheet.Cells[iRow,cTableNameCell].Value;
aFieldDetails[fieldCount].fFieldName := FieldName; //ERROR LINE
ShowMessage('3 -- iRow --> ' + IntToStr(iRow));
FldWithChar := aFieldDetails[fieldCount].fFieldName;
FldWithoutChar := NameWithoutAnyChar(FldWithChar, WordList);
FldList.Add(FldWithChar + '=' + FldWithoutChar);
WordList.Clear;
ShowMessage('4 -- iRow --> ' + IntToStr(iRow));
if (aFieldDetails[fieldCount].fFieldName = '') then
begin
ShowMessage('Field Name cannot be blank. TableName: '+iTableName);
exit;
end;
aFieldDetails[fieldCount].fType := Excel.ActiveSheet.Cells[iRow,3].Value;
aFieldDetails[fieldCount].fShortAlias := Excel.ActiveSheet.Cells[iRow,4].Value;
aFieldDetails[fieldCount].fLongAlias := Excel.ActiveSheet.Cells[iRow,5].Value;
aFieldDetails[fieldCount].fDomainName := Excel.ActiveSheet.Cells[iRow,6].Value;
aFieldDetails[fieldCount].fFieldAttributes.CommaText := Excel.ActiveSheet.Cells[iRow,7].Value;
aFieldDetails[fieldCount].fComments := Excel.ActiveSheet.Cells[iRow,8].Value;
Inc(fieldCount);
Inc(iRow);
end;
//Once new table row will be fouund it will call below method to create a dataview file for current table
ShowMessage('5 -- iRow --> ' + IntToStr(iRow));
GenerateDataviewFiles(aTableDetails, aFieldDetails, FldList, fieldCount-1);
ShowMessage('6 -- iRow --> ' + IntToStr(iRow));
end; //End of If condition
end; //End of outer most while loop
finally
FreeAndNil(WordList);
FreeAndNil(FldList);
Excel.Workbooks.Close;
Excel.Quit;
Excel := Unassigned;
end;
end;
end.
我评论了 //错误行,我收到了访问冲突错误。
我在这里做的是,创建 TFieldDetails数组并希望在另一个文件中循环它。
请帮我解决这个问题,因为我是delphi的新手。
答案 0 :(得分:4)
问题在于您尝试访问超出范围的aFieldDetails
索引。您应该在此之前设置动态数组的长度。像这样:
...
SetLength(aFieldDetails, fieldCount+1);
aFieldDetails[fieldCount].fFieldName := FieldName; //ERROR LINE
...
但是,除非您知道自开始以来总共有多少字段,否则性能会很差。这是因为每次调用SetLength
时,都会分配另一块内存,并将整个数组复制到其中。
我建议您使用TList
,即使您不知道要将多少项添加到列表中,也会尝试保持良好的效果。
答案 1 :(得分:3)
您忘记初始化动态数组aFieldDetails
。因此,当您尝试使用索引fieldCount
写入时,其长度仍为零。
如果您知道字段总数,则应通过调用
来预先分配完整数组SetLength(aFieldDetails, TheTotalFieldCount);
如果您事先不知道总计数,则可以使用列表或其他动态数据结构,因为每次添加项目时重新分配在性能方面都非常昂贵。
aFieldDetailList := TList.Create;
try
while (Excel.ActiveSheet.Cells[iRow,cTableCell].Value <> '') AND
(Excel.ActiveSheet.Cells[iRow,cTableCell].Value <> cTable) do //Will create record until another table will found
begin
New(aFieldDetail); // create a new instance of aFieldDetail; aFieldDetail is of pointer type "^TFieldDetails"
// do your loop work
end;
// do your after-loop work
finally
// free all allocated memory
for aFieldDetail in aFieldDetailList do
Dispose(aFieldDetail);
FreeAndNil(aFieldDetailList);
end;