Delphi-使用VarArrayCreate在Excel数据范围内循环

Delphi-使用VarArrayCreate在Excel数据范围内循环,excel,delphi,Excel,Delphi,Delphi Tokyo-我正在使用Delphi在加载操作之前进行一些Excel电子表格预处理。我正在尝试将Excel区域读取到VarArray中,在数组中循环以进行清理(在本例中,它是一个邮政编码列。如果它是4位zipcode,则前缀为“0”),然后将VarArray写回Excel区域。一切都编译好了,但我在第一次访问VarArray时收到一条错误消息。具体错误为“变量或安全数组索引超出范围”。我的VarArray从excel范围的第2行开始。知道我为什么会犯这个错误吗? 我已经尝试在这里尽可

Delphi Tokyo-我正在使用Delphi在加载操作之前进行一些Excel电子表格预处理。我正在尝试将Excel区域读取到VarArray中,在数组中循环以进行清理(在本例中,它是一个邮政编码列。如果它是4位zipcode,则前缀为“0”),然后将VarArray写回Excel区域。一切都编译好了,但我在第一次访问VarArray时收到一条错误消息。具体错误为“变量或安全数组索引超出范围”。我的VarArray从excel范围的第2行开始。知道我为什么会犯这个错误吗? 我已经尝试在这里尽可能地简化代码

function PROCESS_ZIP_CODE_5DIGIT_MIN(P1,P2 : String): integer;
var

MyColumnLetter : String;
thisSheet : _Worksheet;
i : Integer;
CellText : String;

 arrData: Variant;
 myRange : ExcelRange;
 RangeStartAddr, RangeEndAddr : String;
begin

  MyColumnLetter := 'H';
  thisSheet := oExcel.ActiveSheet as _Worksheet;

  {create variant array where we'll copy our data}
  arrData := VarArrayCreate([2, 500 ], varVariant);

  // Get the Range Address
  RangeStartAddr := MyColumnLetter + '2';
  RangeEndAddr :=   MyColumnLetter + IntToStr(500);

  // Now read the data into the VarArray
   myRange :=   thisSheet.range[RangeStartAddr, RangeEndAddr];
   arrData := myRange.Value2;

 // Now process the data itself
   for i  := 2 to 500 do
   begin

    CellText := arrData[i]; // ERROR ON THIS LINE
    if Length(CellText) = 4 then
    begin
      CellText:= '0' + CellText;
      arrData[i] := CellText;
    end;
   end;

   // Now write the VarArray back to the spreadsheet
   thisSheet.range[RangeStartAddr, RangeEndAddr].Value2 :=  myRange;
end;

我不会尝试整理你的代码,因为它有一堆错误

下面是一个工作代码示例,用于将一系列单元格(在本例中,
H1
通过
J
中最后填充的单元格)检索到变量数组中,然后将该数组放入Delphi
TStringGrid
。虽然代码使用后期绑定而不是早期绑定,但它清楚地演示了在从Excel读取范围时如何正确使用
VarArrayCreate

var
  Excel, Book, Sheet, Range1: OleVariant;
  i, j: Integer;
  Data: Variant;
const
  // Obtained at https://msdn.microsoft.com/en-us/library/office/ff820880.aspx
  xlDown = -4121;
begin
  Excel := CreateOleObject('Excel.Application');
  try
    Book := Excel.WorkBooks.Open('E:\TempFiles\Test.xlsx');
    Sheet := Book.Worksheets.Item['Sheet1'];

    // Get tne range we want to extract, in this case all rows of columns H-J.
    // .End(xlDown) finds the last used cell in the indicated column
    Range1 := Sheet.Range['H1', Sheet.Range['J1'].End[xlDown]];
    Data := Range1.Value;

    // Get the number of columns and rows from the array itself. The addition
    // of 1 is for the fixed row and column, and to synch up with the Data
    // array being 1 based instead of 0
    StringGrid1.ColCount := VarArrayHighBound(Data, 2) + 1;
    StringGrid1.RowCount := VarArrayHighBound(Data, 1) + 1;

    // StringGrid.Cells are accessed in Col, Row order, but the
    // array is returned in Row, Col layout. Note the swap in
    // i and j below in the subscripts to accomodate that fact.
    for i := 1 to StringGrid1.ColCount - 1 do
      for j := 1 to StringGrid1.RowCount - 1 do
        StringGrid1.Cells[i, j] := Data[j, i];

  finally
    // Clean up all references so Excel will close cleanly
    Range1 := null;
    Sheet := null;
    Book := null;
    Excel.Quit;
    Excel := null;
  end;

我不会尝试整理你的代码,因为它有一堆错误

下面是一个工作代码示例,用于将一系列单元格(在本例中,
H1
通过
J
中最后填充的单元格)检索到变量数组中,然后将该数组放入Delphi
TStringGrid
。虽然代码使用后期绑定而不是早期绑定,但它清楚地演示了在从Excel读取范围时如何正确使用
VarArrayCreate

var
  Excel, Book, Sheet, Range1: OleVariant;
  i, j: Integer;
  Data: Variant;
const
  // Obtained at https://msdn.microsoft.com/en-us/library/office/ff820880.aspx
  xlDown = -4121;
begin
  Excel := CreateOleObject('Excel.Application');
  try
    Book := Excel.WorkBooks.Open('E:\TempFiles\Test.xlsx');
    Sheet := Book.Worksheets.Item['Sheet1'];

    // Get tne range we want to extract, in this case all rows of columns H-J.
    // .End(xlDown) finds the last used cell in the indicated column
    Range1 := Sheet.Range['H1', Sheet.Range['J1'].End[xlDown]];
    Data := Range1.Value;

    // Get the number of columns and rows from the array itself. The addition
    // of 1 is for the fixed row and column, and to synch up with the Data
    // array being 1 based instead of 0
    StringGrid1.ColCount := VarArrayHighBound(Data, 2) + 1;
    StringGrid1.RowCount := VarArrayHighBound(Data, 1) + 1;

    // StringGrid.Cells are accessed in Col, Row order, but the
    // array is returned in Row, Col layout. Note the swap in
    // i and j below in the subscripts to accomodate that fact.
    for i := 1 to StringGrid1.ColCount - 1 do
      for j := 1 to StringGrid1.RowCount - 1 do
        StringGrid1.Cells[i, j] := Data[j, i];

  finally
    // Clean up all references so Excel will close cleanly
    Range1 := null;
    Sheet := null;
    Book := null;
    Excel.Quit;
    Excel := null;
  end;

您尝试过VarArrayPut吗?在
arrData:=VarArrayCreate([2500],varvarvariant)之后使用
arrData:=myRange.Value2为arrData赋值,该赋值将覆盖var数组。这是否也返回一个var数组?@nil:即使它也返回一个var数组,它仍然会覆盖使用
VarArrayCreate
创建的数组。我认为没有必要调用
VarArrayCreate
。新数组可以有不同的边界。在进入循环之前必须检查这些。我的代码示例基于这里的工作。。。它将stringGrid复制到Excel。显然我做错了什么…:(您的代码示例不同。您使用字符串访问单元格(
MyColumnLetter+'2'
),而它们使用数字:
[wb.workSheets[1]。单元格[1,1]等。)
。你确定收到了什么吗?而且你可能也需要一个二维数组,即使二维数组的大小只有1。只需逐字尝试他们的exampe,然后根据需要修改它,不断检查它是否仍然有效。如果出现问题,你知道你最后做了什么,这一定是问题所在。你试过VararyPU吗t?在
arrData:=VarArrayCreate([2500],varVariant)之后;
您使用
arrData:=myRange.Value2;
为arrData赋值,该赋值将覆盖您的var数组。这是否也返回一个var数组?@nil:即使它也返回一个var数组,它仍然会覆盖使用
VarArrayCreate
创建的数组。我认为调用
VarArrayCreate
是不必要的Y.和新数组可能有不同的边界。在进入循环之前必须检查这些边界。我的代码示例基于此处的工作…将stringGrid复制到Excel。显然我做错了…:(您的代码示例不同。您使用字符串访问单元格(
MyColumnLetter+'2'
),而它们使用数字:
[wb.workSheets[1]。单元格[1,1]等
。你确定收到了什么吗?而且你可能也需要一个二维数组,即使二维数组的大小只有1。只需逐字尝试他们的exampe,然后根据你的需要修改它,不断检查它是否仍然有效。如果出了问题,你知道你最后做了什么,这一定是问题所在。这给了我eeded。我真的很感谢这些深入的评论。仅供参考-我无法获得要编译的范围1:=行(Excel 2016),因此我不得不更改它。如果我更改范围,使其从H1到H50,我会预期“数据”变量是一个一维数组,但它仍然是二维的(根据VarArrayDimCount(数据))。你能解释一下原因吗?这给了我所需的信息。我非常感谢你的深入评论。仅供参考-我无法获得要编译的Range1:=行(Excel 2016)所以我必须改变它。如果我改变范围,使它从H1到H50,我会期望“数据”变量是一个一维数组,但它仍然是二维的(根据VarArrayDimCount(Data)。你能解释为什么吗?