Как записывать данные из вариантного массива в Excel?
Запись данных из вариантного массива (VarArray) очень хорошо расписана в статьях "По волнам интеграции… III" и "Зарисовка на тему экспорта в Excel". Для разнообразия, приведу еще раз этот вариант быстрого экспорта в Excel.
Внимание! Если вы пытаетесь записать в область одну строку, то МАССИВ все равно ДОЛЖЕН БЫТЬ ДВУМЕРНЫМ! Т.е. varData := VarArrayCreate([1, 1, 1, ColumnCount], varVariant); При записи массива вы должны указать в адресе области ячеек Range ВСЮ область для заполнения.
Delphi:
procedure CopyFromDataSet(ASheet: _WorkSheet; DataSet: TDataSet);
var
R, C: Integer; vData: Variant; begin
DataSet.Last; // специально для IBX
// строки на одну больше, чем в датасете - для шапки
vData := VarArrayCreate([0, DataSet.RecordCount, 1, DataSet.FieldCount], varVariant); for C := 0 to DataSet.FieldCount - 1 do
vData[0, C + 1] := DataSet.Fields[C].DisplayLabel; DataSet.First; R := 1; while not DataSet.Eof do begin
for C := 0 to DataSet.FieldCount - 1 do
case DataSet.Fields[C].DataType of
ftString, ftFixedChar, ftWideString: vData[R, C + 1] := #39 + DataSet.Fields[C].Value; else vData[R, C + 1] := DataSet.Fields[C].Value; end; Inc(R); DataSet.Next; end; // укажем всю область, в которую будут записаны данные из массива
with ASheet do with Range['A1', Cells.Item[DataSet.RecordCount + 1, DataSet.FieldCount]] do begin
Formula := vData; Borders.Weight := xlHairline; EntireColumn.AutoFit; end; vData := Unassigned; // освободим память сами
// настройка внешнего вида
with ASheet do Range['A1', Cells.Item[1, DataSet.FieldCount]].Interior.ColorIndex := 15; ASheet.Application.ActiveWindow.SplitRow := 1; ASheet.Application.ActiveWindow.FreezePanes := True; ASheet.Application.ActiveWindow.DisplayGridlines := False;
end;
C#:
// данные будут взяты из таблицы EMPLOYEE из файла DBDEMOS.MDB string dbFile = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles); dbFile += @"\Borland Shared\Data\dbdemos.mdb"; // заменим путь к файлу dbdemos dbFile = Regex.Replace(oleDbConnection1.ConnectionString, @"^(?<start>.*?;Data Source=)(?<db>[^;]*)(?<end>;.*)$", "${start}" + dbFile + "${end}"); oleDbConnection1.ConnectionString = dbFile; try { oleDbDataAdapter1.Fill(dataSet1, "employee"); oleDbConnection1.Close(); // закроем соединение // DataTable tblEmployee = dataSet1.Tables["employee"]; dataGrid1.DataSource = tblEmployee; // dataSet1.Tables["employee"]; // создадим двумерный массив для экспорта object[,] arrEmployee = (object[,]) Array.CreateInstance(typeof(object), new int[2] {tblEmployee.Rows.Count + 1, tblEmployee.Columns.Count}, // длины массива new int[2] {0, 1}); // начальные индексы строк и столбцов // заголовки for (int i = 0; i < tblEmployee.Columns.Count; i++) arrEmployee[0, i + 1] = tblEmployee.Columns[i].Caption; // данные for (int R = 0; R < tblEmployee.Rows.Count; R++) for (int C = 0; C < tblEmployee.Columns.Count; C++) { arrEmployee[R + 1, C + 1] = tblEmployee.Rows[R][C]; Application.DoEvents(); } Excel.Worksheet oSheet = null; Excel.Range oRng = null; Excel.Application XL = new Excel.Application(); try { XL.Visible = true; XL.Interactive = false; XL.Workbooks.Add(Type.Missing); oSheet = (Excel.Worksheet) XL.ActiveSheet; oRng = oSheet.get_Range(oSheet.Cells[1, 1], oSheet.Cells[tblEmployee.Rows.Count + 1, tblEmployee.Columns.Count]); oRng.Formula = arrEmployee; // запись данных oRng.EntireColumn.AutoFit(); oRng.Borders.LineStyle = Excel.XlLineStyle.xlContinuous; oRng.Borders.Weight = Excel.XlBorderWeight.xlHairline; // шапка oRng = oSheet.get_Range(oSheet.Cells[1, 1], oSheet.Cells[1, tblEmployee.Columns.Count]); oRng.Interior.ColorIndex = 15; // 25% серого oRng.Interior.Pattern = Excel.XlPattern.xlPatternSolid; XL.ActiveWindow.SplitRow = 1; XL.ActiveWindow.FreezePanes = true; XL.ActiveWindow.DisplayGridlines = false; XL.ActiveWorkbook.Saved = true; this.Activate(); } finally { oSheet = null; XL.Interactive = true; XL.UserControl = true; XL = null; } dataSet1.Tables.Remove(tblEmployee); } catch (Exception ex) { if (oleDbConnection1.State == ConnectionState.Open) oleDbConnection1.Close(); MessageBox.Show(ex.Message); }