前两篇研究了一下在连接数据库后,TStringGrid控件数据的填充。还有将TStringGrid的填充数据复制到剪贴板,再通过剪贴板把数据粘贴到其它地方。
现在,再来研究一下,如何把当前TStringGrid控件中的数据整表,按照所选路径保存成Excel文件。
一、环境
Windows10
RAD Studio 10 Seattle
SQL Server 2014 Management Studio
二、相关控件
还是继续用之前两篇创建的窗体展开,添加一个Button2按钮(用作导出的触发)和一个SaveDialog1(文件导出路径的选择)
三、创建生成Excel的调用过程StringGridToExcel
可以概括为三个步骤:创建Excel文件——数据填充到excel——Excel保存
1、用Excel本身的文件命名、选径保存
//StringGridToExcel的过程,像这种公共的、会多处使用到的方法,可以将它们写到一起去,哪个窗体要用的话在uses处添加引用
//记得要在窗体头部相应地生成procedure StringGridToExcel(StringGrid1: TStringGrid);
procedure TForm1.StringGridToExcel(StringGrid1: TStringGrid); // 传参参数为TStringGrid,既显示到StringGrid1的数据集
var
i, j: integer;
filename: string;
excel: OleVariant;
savedialog: tsavedialog;
begin
screen.Cursor := crHourGlass; //使鼠标指针形状为沙漏状。(可以用此表示程序正在执行中)
try
excel := CreateOleObject('Excel.Application'); //需要引用ComObj,才能使用OLE创建Excel文件
excel.workbooks.add; //创建一个工作簿
except
screen.cursor := crDefault; //使鼠标指针恢复成箭头状态
showmessage('无法调用Excel!');
exit;
end;
//将StringGrid1中的数据循环填充到excel
///就和之前的StringGrid填充数据集是一致的,只不过把数据来源ADOQuery1换成StringGrid1,StringGrid1.Cells换成了excel.Cells
for i := 0 to StringGrid1.RowCount - 1 do
begin
for j := 0 to StringGrid1.ColCount - 1 do
begin
excel.Cells[i + 1, j + 1] := StringGrid1.Cells[j, i];
end;
end;
try
//将 excel的工作簿按路径(filename)保存
excel.ActiveWorkbook.SaveAs(filename); // ActiveWorkbook.SaveAs(文件名,)
except
excel.Quit;
screen.cursor := crDefault;
exit;
end;
// excel.Visible := true; //Excel是否允许直接打开编辑
screen.cursor := crDefault;
end;
- 在Button2按钮的点击事件中调用【StringGridToExcel】
procedure TForm1.Button2Click(Sender: TObject);
begin
StringGridToExcel(StringGrid1);
end;
- 运行结果
弹出了Excel的保存窗口
excel中成功地导出了StringGrid的数据集,并且文件名自动按序生成【工作簿5】
2、用TSaveDialog控件的Excel文件命名、选径保存
procedure TForm1.StringGridToExcel(StringGrid1: TStringGrid); // 传参参数为TStringGrid,既显示到StringGrid1的数据集
var
i, j, k, l: integer;
filename: string;
excel: OleVariant;
savedialog: tsavedialog;
begin
screen.Cursor := crHourGlass; //使鼠标指针形状为沙漏状。(可以用此表示程序正在执行中)
try
excel := CreateOleObject('Excel.Application'); //需要引用ComObj,才能使用OLE创建Excel文件
excel.workbooks.add; //创建一个工作簿
except
screen.cursor := crDefault; //使鼠标指针恢复成箭头状态
showmessage('无法调用Excel!');
exit;
end;
savedialog := tsavedialog.Create(nil);
savedialog.Filter := 'Excel文件(*.xls)|*.xls';
if savedialog.Execute then //文件保存控件被执行
begin
if FileExists(savedialog.FileName) then //如果本地有与savedialog写的文件名相同的文件名
try
if application.messagebox('该文件已经存在,要覆盖吗?', '询问', mb_yesno + mb_iconquestion) = idyes then //messagebox信息弹窗
DeleteFile(PChar(savedialog.FileName)) ///选择覆盖原文件,是,则删掉
else
begin//不覆盖源文件,则退出excel,鼠标形状还原,退出整个事件
excel.Quit;
savedialog.free;
screen.cursor := crDefault;
Exit;
end;
except//报错的话,则退出excel,鼠标形状还原,退出整个事件
excel.Quit;
savedialog.free;
screen.cursor := crDefault;
Exit;
end;
filename := savedialog.FileName; //文件名为TSaveDialog中所赋值的文件名
end;
savedialog.free;
if filename = '' then //如果TSaveDialog取消,要让excel退出,不然还是会弹出excel本身的文件保存窗口
begin
excel.Quit;
screen.cursor := crDefault;
exit;
end;
//将StringGrid1中的数据循环填充到excel
///就和之前的StringGrid填充数据集是一致的,只不过把数据来源ADOQuery1换成StringGrid1,StringGrid1.Cells换成了excel.Cells
for i := 0 to StringGrid1.RowCount - 1 do
begin
for j := 0 to StringGrid1.ColCount - 1 do
begin
excel.Cells[i + 1, j + 1] := StringGrid1.Cells[j, i];
end;
end;
try
//判断文件名后缀是不是.xls/.xlsx(这里就写.xlsx吧)
//上面用Excel本身的文件命名、选径保存,没有判断文件名是因为文件名没有TSaveDialog的赋值,是为空的。
if copy(filename, length(filename) - 3, 4) <> '.xlsx' then //Copy(处理的字符,开始截取的位置,截取位数)
filename := filename + '.xlsx';
//将 excel的工作簿按所选路径(filename)保存
excel.ActiveWorkbook.SaveAs(filename); // ActiveWorkbook.SaveAs(文件名,)
except
excel.Quit;
screen.cursor := crDefault;
exit;
end;
//excel.Visible := true; //Excel是否允许直接打开编辑
screen.cursor := crDefault;
excel.Quit;
end;
- 运行结果
用TSaveDialog控件的话会弹出这么一个,在本机选择文件保存路径【另存为】的窗体
3、其他
①excel获取数据前可以判断一下,导出的数据是否超过Excel的最大可容行数
- 对2003版,最大行数是65536行
- 对2007以上版本,最大行数是1048576行
if StringGrid1.RowCount > 1048576 then //判断StringGrid1取出的数据集行数
begin
if application.messagebox('需要导出的数据过大,Excel最大只能容纳1048576行,是否还要继续?', '询问', mb_yesno + mb_iconquestion) =idno then
exit;
end;
②对excel表格可以进行一些宽高、字体大小、单元格背景色…的设置
excel.ActiveSheet.Columns[1].ColumnWidth := 30; //设置excel中第1列的列宽为30
excel.ActiveSheet.Rows[1].RowHeight := 30; //设置excel中第1行的行高为30
excel.ActiveSheet.Rows[1].Font.Name := '隶书'; //设置excel中第1行的字体为'隶书'
excel.ActiveSheet.Rows[1].Font.Color := clBlue; //设置excel中第1行的字体
excel.ActiveSheet.Rows[1].Font.Bold := True; //设置excel中第1行的字体加粗
excel.ActiveSheet.Rows[1].Font.UnderLine := True; //设置excel中第1行的字体添加下划线
//合并最后一列+1、最后一行+1之后的单元格
Vrange := excel.range[excel.cells[StringGrid1.RowCount + 1, 1], excel.cells[StringGrid1.RowCount + 1, StringGrid1.ColCount]];
Vrange.Select;
Vrange.Merge(True);
Vrange.Font.Size := 20; //合并后单元格内容的字体大小
Vrange.Font.Bold := True; //合并后单元格内容的字体加粗
Vrange.Interior.ColorIndex := 7; //合并单元格后的背景色,7为粉色(Interior.ColorIndex 色彩列表)
excel.cells[StringGrid1.RowCount + 1, 1] := '对最后一行进行合并一下看'; //excel的单元格赋值
- 运行结果
4、结束
其实,还可以在procedure TForm1.StringGridToExcel(StringGrid1: TStringGrid);中设置多一个参数传值。
比如可以传值文件名,procedure TForm1.StringGridToExcel(StringGrid1: TStringGrid;para_filename:string);就可以在触发按钮调用该过程时,将你对应的自定义文件名传参过来。
不过这样的话,excel本身自带的保存功能会直接将文件保存到默认路径,或者传过来的带路径前缀的文件名。建议用TSaveDialog控件,直接将SaveDialog1.FileName的值设为传过来的para_filename。
procedure TForm1.Button2Click(Sender: TObject);
begin
StringGridToExcel(StringGrid1,'导出人员表信息'); //'D:\导出人员表信息'加个路劲就直接保存到路径下,不然直接保存到默认路径下
end;
//也可以在文件名中添加当前时间:FormatDateTime('YYYY-MM',Now())
就不再多展开了,每个都试试,慢慢调试。
【Delphi】将TStringGrid控件中的数据按照所选路径保存成Excel文件,记录,打板!