Можно ли экспортировать VirtualStringTree в Excel или CSV?
Я использую Delphi 2007 и пытаюсь сохранить свои записи данных VirtualStringTree в формате Excel или CSV.
Можно ли экспортировать VirtualStringTree в Excel или CSV?
Я использую Delphi 2007 и пытаюсь сохранить свои записи данных VirtualStringTree в формате Excel или CSV.
У нас есть вспомогательный класс ExcelWriter
, который может выгружать все виды данных в Excel, например.
В этом случае быстрый способ (и простой для копирования и вставки здесь) — это перегрузка, которая может выгружать массив вариантов в Excel:
class function TExcelWriter.ExportToExcelVariantArray(const VArray: Variant; const Title, SubTitle: WideString): Boolean;
var
xl: OleVariant;
workbook: OleVariant;
worksheet: OleVariant;
range: OleVariant;
Rowcount, ColumnCount: Integer;
HeaderRowIndex: Integer;
s: WideString;
begin
Result := False;
if not VarIsArray(VArray) then
raise EExcelWriterException.Create('ExportToExcelVariantArray: Supplied variant is not an array');
if VarArrayDimCount(VArray) <> 2 then
raise EExcelWriterException.Create('ExportToExcelEVariantArray: Supplied variant array does not have 2 dimensions ('+IntToStr(VarArrayDimCount(VArray))+')');
ColumnCount := VarArrayHighBound(VArray, 2) - VarArrayLowBound(VArray, 2); //2 for "leftmost dimension"
rowCount := VarArrayHighBound(VArray, 1) - VarArrayLowBound(VArray, 1); //1 for "leftmost dimension"
try
xl := CreateOleObject('Excel.Application');
except
on E:Exception do
begin
if (E is EOleSysError) then
begin
if EOleSysError(E).ErrorCode = CO_E_CLASSSTRING then
raise EExcelWriterException.Create('Excel is not installed.'+CRLF+
'Could not load "Excel.Application" object (Co_E_CLASSSTRING)')
else
raise;
end
else
raise;
end;
end;
try
xl.ScreenUpdating := False;
xl.DisplayAlerts := False; // Don't display dialogs such as "save changes to workbook".
workbook := xl.Workbooks.Add;
try
Worksheet := Workbook.Worksheets[1];
try
Worksheet.Activate;
Worksheet.Cells.WrapText := False;
HeaderRowIndex := 1; //Rows&Columns in Excel start at one.
range := TExcelWriter.GetRange(worksheet, HeaderRowIndex, 1, HeaderRowIndex+RowCount, ColumnCount);
range.Value := VArray;
//Bold the header row
Worksheet.Rows[HeaderRowIndex].Font.Bold := True;
Worksheet.Rows[HeaderRowIndex].Font.Underline := True;
Worksheet.Columns.AutoFit;
//Set printed header&footer
if Copy(Title, 1, 2) = '@@' then
s := Copy(Title, 3, MaxInt)
else
s := Title;
if SubTitle <> '' then
begin
if s <> '' then s := s+#13;
s := s + SubTitle;
end;
TExcelWriter.SetHeaderAndFooters(Worksheet,
s, '', '',
'&D &T', '', 'Page &P of &N');
finally
Worksheet := Unassigned;
end;
finally
Workbook := Unassigned;
end;
//When all done
xl.ScreenUpdating := True;
xl.Visible := True;
xl.UserControl := True; // Very important, prevents Excel from going
// away when we nil out our reference to it below.
finally
xl := Unassigned;
end;
Result := True;
end;
У нас есть TVirtualListView
потомок TVirtualStringTree
, который упростил переход на VirtualTrees (у него TVirtualListItem
и т. д.). Затем у него есть вспомогательный метод ContentToVariantArray
, который похож на ContentToHtml
и ContentToRtf
:
function TVirtualListView.ContentToVariantArray: Variant;
var
Columns: TColumnsArray;
VArray: Variant;
Node: PVirtualNode;
ColumnCount: Integer;
RowCount: Integer;
nRow: Integer;
i: Integer;
begin
Columns := Self.Columns.GetVisibleColumns;
ColumnCount := Length(Columns);
RowCount := Self.Items.Count+1; //+1 for the heaader
VArray := VarArrayCreate([0, RowCount-1, 0, ColumnCount-1], varOleStr); //Docs say cannot use varString, must be varOleStr (which is a BSTR i.e. WideString)
nRow := 0;
for i := 0 to ColumnCount-1 do
begin
VArray[nRow, i] := Self.Columns.Items[Columns[i].Index].Text;
end;
Node := Self.GetFirst;
while Assigned(Node) do
begin
Inc(nRow);
for i := 0 to ColumnCount-1 do
begin
VArray[nRow, i] := Self.Text[Node, Columns[i].Index];
end;
Node := Self.GetNextSibling(Node);
end;
Result := VArray;
end;
Основным недостатком здесь является то, что мы автоматизируем Excel, чтобы использовать его. Это означает, что вашему клиенту/серверу потребуется установленный Excel.
Вышеприведенный код показывает пользователя Excel (необходимость сохранять файл на жесткий диск только для того, чтобы просмотреть его расточительно), а не создание файла экспорта. Но было бы несложно вызвать .Save
или какой-либо другой API.
CSV было бы проще.
Ваши данные — это ваши собственные данные, поскольку VirtualStringTree не содержит данных, это виртуальный контейнер. Таким образом, если ваше виртуальное строковое дерево является представлением списка TMyObjects (контейнера), его вывод в CSV должен быть относительно тривиальным, и содержимое виртуального дерева будет действительно иметь значение только в том случае, если ваши столбцы могут быть в другом порядке или набор видимых столбцов выполнен.
Я предлагаю вам изучить бесплатный JVCL JvCsvDataSet, который является действительно простым способом записи файлов CSV.
Если вам действительно нужен вывод XLS, для этого есть библиотеки.
Написание CSV построено (так же, как html):
var ss : AnsiString;
...
if ExtractFileExt(DestFileName)='.htm'
then
ss:=VST.ContentToHtml(tstAll, 'Html exp')
else
ss:=VST.ContentToText(tstAll, ';');
with TFileStream.Create(DestFileName, fmCreate or fmShareDenyWrite) do
begin
Write(ss[1], length(ss));
Free;
end;