與 ListView 版本的關鍵差異
- 資料來源為
TDataSet(透過 DBGrid->DataSource->DataSet)
- 匯出內容 = 目前資料集顯示的所有記錄(含篩選後結果)
- 欄位對應透過
DBGrid->Columns[i]->FieldName 取得
- 需檢查
DataSet->Active 避免未開啟資料集報錯
DBGrid2Word 完整程式碼
void __fastcall DBGrid2Word(TDBGrid* dbg, String strDocFile) {
if (!dbg->DataSource->DataSet->Active) return; // 資料集未開啟
Variant vWordApp, vTable, vCell;
try { vWordApp = Variant::CreateObject("Word.Application"); }
catch (...) {
MessageBox(0, "啟動 Word 失敗。", "DBGrid2Word", MB_OK|MB_ICONERROR);
return;
}
vWordApp.OlePropertySet("Visible", false);
vWordApp.OlePropertyGet("Documents").OleFunction("Add");
Variant vSelect = vWordApp.OlePropertyGet("Selection");
vSelect.OlePropertyGet("Font").OlePropertySet("Size", dbg->Font->Size);
vSelect.OlePropertyGet("Font").OlePropertySet("Name", dbg->Font->Name.c_str());
int nRowCount = dbg->DataSource->DataSet->RecordCount + 1;
nRowCount = nRowCount < 2 ? 2 : nRowCount;
int nColCount = dbg->Columns->Count;
nColCount = nColCount < 1 ? 1 : nColCount;
vWordApp.OlePropertyGet("ActiveDocument").OlePropertyGet("Tables")
.OleProcedure("Add", vSelect.OlePropertyGet("Range"), nRowCount, nColCount, 1, 0);
vTable = vWordApp.OlePropertyGet("ActiveDocument")
.OleFunction("Range").OlePropertyGet("Tables").OleFunction("Item", 1);
for (int i = 0; i < nColCount; ++i) {
int w = dbg->Columns->Items[i]->Width;
vTable.OlePropertyGet("Columns").OleFunction("Item", i+1)
.OlePropertySet("PreferredWidthType", 3);
vTable.OlePropertyGet("Columns").OleFunction("Item", i+1)
.OlePropertySet("PreferredWidth", w);
}
// 寫入欄位名稱
for (int j = 0; j < dbg->Columns->Count; ++j) {
vCell = vTable.OleFunction("Cell", 1, j+1);
vCell.OlePropertySet("Range", dbg->Columns->Items[j]->FieldName.c_str());
vCell.OlePropertyGet("Shading")
.OlePropertySet("BackgroundPatternColor", 14737632);
}
// 遍歷資料集寫入資料
dbg->DataSource->DataSet->First();
for (int i = 0; i < nRowCount - 1; ++i) {
for (int j = 0; j < dbg->Columns->Count; ++j) {
vCell = vTable.OleFunction("Cell", i+2, j+1);
vCell.OlePropertySet("Range",
dbg->DataSource->DataSet->FieldByName(
dbg->Columns->Items[j]->FieldName)->AsString.c_str());
}
dbg->DataSource->DataSet->Next();
}
vWordApp.OlePropertyGet("ActiveDocument").OleProcedure("SaveAs", strDocFile.c_str());
vWordApp.OlePropertyGet("ActiveDocument").OleProcedure("Close");
Application->ProcessMessages();
vWordApp.OleProcedure("Quit");
Application->ProcessMessages();
vWordApp = Unassigned;
MessageBox(0, "DBGrid2Word 轉換完成!", "DBGrid2Word", MB_OK|MB_ICONINFORMATION);
}
DBGrid2Excel 完整程式碼
void __fastcall DBGrid2Excel(TDBGrid* dbg, String strXlsFile) {
if (!dbg->DataSource->DataSet->Active) return;
Variant vExcelApp, vSheet;
try { vExcelApp = Variant::CreateObject("Excel.Application"); }
catch (...) {
MessageBox(0, "啟動 Excel 失敗。", "DBGrid2Excel", MB_OK|MB_ICONERROR);
return;
}
vExcelApp.OlePropertySet("Visible", false);
vExcelApp.OlePropertyGet("Workbooks").OleFunction("Add", 1);
vSheet = vExcelApp.OlePropertyGet("ActiveWorkbook").OlePropertyGet("Sheets", 1);
vSheet.OleProcedure("Select");
vSheet.OlePropertyGet("Cells").OleProcedure("Select");
vExcelApp.OlePropertyGet("Selection").OlePropertyGet("Font")
.OlePropertySet("Size", dbg->Font->Size);
vExcelApp.OlePropertyGet("Selection").OlePropertyGet("Font")
.OlePropertySet("Name", dbg->Font->Name.c_str());
vExcelApp.OlePropertyGet("Selection").OlePropertyGet("Font")
.OlePropertySet("FontStyle", "常規");
vSheet.OlePropertyGet("Cells", 1, 1).OleProcedure("Select");
int nRowCount = dbg->DataSource->DataSet->RecordCount + 1;
nRowCount = nRowCount < 2 ? 2 : nRowCount;
int nColCount = dbg->Columns->Count;
nColCount = nColCount < 1 ? 1 : nColCount;
for (int i = 0; i < nColCount; ++i) {
int w = dbg->Columns->Items[i]->Width;
vExcelApp.OlePropertyGet("Columns", i+1)
.OlePropertySet("ColumnWidth", w / 7); // Excel 欄寬單位不同
}
for (int j = 0; j < dbg->Columns->Count; ++j) {
vExcelApp.OlePropertyGet("Rows", 1).OlePropertySet("RowHeight", 20);
vSheet.OlePropertyGet("Cells", 1, j+1)
.OlePropertySet("Value", dbg->Columns->Items[j]->FieldName.c_str());
Variant vInter = vSheet.OlePropertyGet("Cells", 1, j+1).OlePropertyGet("Interior");
vInter.OlePropertySet("ColorIndex", 15);
vInter.OlePropertySet("Pattern", 1);
vInter.OlePropertySet("PatternColorIndex", -4105);
}
dbg->DataSource->DataSet->First();
for (int i = 0; i < nRowCount - 1; ++i) {
vExcelApp.OlePropertyGet("Rows", i+2).OlePropertySet("RowHeight", 16);
for (int j = 0; j < dbg->Columns->Count; ++j) {
vSheet.OlePropertyGet("Cells", i+2, j+1)
.OlePropertySet("Value",
dbg->DataSource->DataSet->FieldByName(
dbg->Columns->Items[j]->FieldName)->AsString.c_str());
}
dbg->DataSource->DataSet->Next();
}
vExcelApp.OlePropertyGet("ActiveWorkbook").OleFunction("SaveAs", strXlsFile.c_str());
vExcelApp.OleFunction("Quit");
vSheet = Unassigned; vExcelApp = Unassigned;
MessageBox(0, "DBGrid2Excel 轉換完成!", "DBGrid2Excel", MB_OK|MB_ICONINFORMATION);
}
呼叫範例
DBGrid2Word(DBGrid1, "C:\\Export\\Data.doc");
DBGrid2Excel(DBGrid1, "C:\\Export\\Data.xls");
關鍵細節提醒
- RecordCount 可靠性:部分資料集 (如 uni-directional cursor)
RecordCount 可能為 -1,建議改用 while (!Eof) { ... Next(); } 迴圈
- 欄位型別轉換:此處統一用
AsString,若需保留數值/日期格式,請依 Field->DataType 分別處理
- 大量資料優化:同 ListView 版,建議改用陣列批次寫入
Range.Value
- 資料集狀態還原:匯出前後建議保存/還原
Filter、Index、游標位置
適用場景
- 資料庫報表匯出
- 使用者自訂查詢結果另存
- 列印預覽前的資料備份