unit Unit1; |
interface |
uses |
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, |
Dialogs, ExtCtrls, Grids, DBGridEh, DB, ADODB, StdCtrls, Excel2000, |
OleServer; |
type |
TForm1 = class (TForm) |
ADOConnection1: TADOConnection; |
ADOQuery1: TADOQuery; |
DataSource1: TDataSource; |
DBGridEh1: TDBGridEh; |
Panel1: TPanel; |
ComboBox1: TComboBox; |
Edit1: TEdit; |
Button1: TButton; |
Button2: TButton; |
ExcelApplication1: TExcelApplication; |
ExcelWorksheet1: TExcelWorksheet; |
ExcelWorkbook1: TExcelWorkbook; |
procedure FormClose(Sender: TObject; var Action: TCloseAction); |
procedure FormCreate(Sender: TObject); |
procedure FormDestroy(Sender: TObject); |
procedure ComboBox1Change(Sender: TObject); |
procedure Button1Click(Sender: TObject); |
procedure Button2Click(Sender: TObject); |
private |
{ Private declarations } |
public |
{ Public declarations } |
end ; |
var |
Form1: TForm1; |
implementation |
uses ExportMultiTitle; |
{$R *.dfm} |
procedure TForm1 . FormClose(Sender: TObject; var Action: TCloseAction); |
begin |
Action:=caFree; |
end ; |
procedure TForm1 . FormCreate(Sender: TObject); |
var |
conStr: string ; |
i : integer ; |
begin |
conStr:= 'Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;Data Source=' ; |
conStr:=conStr+ExtractFilePath(Application . ExeName)+ 'test.mdb;' ; |
conStr:=conStr+ 'Mode=Share Deny None;Extended Properties="";Jet OLEDB:System database="";Jet OLEDB:Registry Path="";Jet OLEDB:Database Password="";' ; |
conStr:=conStr+ 'Jet OLEDB:Engine Type=5;Jet OLEDB:Database Locking Mode=1;Jet OLEDB:Global Partial Bulk Ops=2;' ; |
conStr:=conStr+ 'Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="";' ; |
conStr:=conStr+ 'Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don' 't Copy Locale on Compact=False;' ; |
conStr:=conStr+ 'Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False' ; |
ADOConnection1 . ConnectionString:=conStr; |
ADOConnection1 . Open; |
ADOQuery1 . Open; |
for i:= 0 to AdoQuery1 . Fields . Count- 1 do |
combobox1 . Items . Add(AdoQuery1 . Fields[i].FieldName); |
ComboBox1 . ItemIndex:= 0 ; |
ComboBox1 . OnChange(Self); |
end ; |
procedure TForm1 . FormDestroy(Sender: TObject); |
begin |
ADOQuery1 . Close; |
ADOConnection1 . Close; |
end ; |
procedure TForm1 . ComboBox1Change(Sender: TObject); |
begin |
Edit1 . Text:=ADOQuery1 . Fields[ComboBox1 . ItemIndex].DisplayLabel; |
end ; |
procedure TForm1 . Button1Click(Sender: TObject); |
begin |
ADOQuery1 . Fields[ComboBox1 . ItemIndex].DisplayLabel:=Edit1 . Text; |
end ; |
procedure TForm1 . Button2Click(Sender: TObject); |
var |
i,j: Integer ; |
dT,dL,dR,dB: Integer ; |
Ra:Variant; |
begin |
Try |
ExcelApplication1 . Connect; |
ExcelWorkbook1 . ConnectTo(ExcelApplication1 . Workbooks . Add(EmptyParam, 0 )); |
ExcelWorkSheet1 . ConnectTo(ExcelWorkBook1 . Sheets[ 1 ] as _WorkSheet); |
ExcelApplication1 . Caption := '通用客户打印调用 Microsoft Excel' ; |
ExcelApplication1 . Visible[ 0 ]:= True ; |
ExportMyCell(ADOQuery1 . Fields); |
for i:= 0 to r- 1 do |
for j:= 0 to c- 1 do |
if MyCells[i,j].Used then |
begin |
if (MyCells[i,j].Rect . Top=MyCells[i,j].Rect . Bottom) |
and (MyCells[i,j].Rect . Left=MyCells[i,j].Rect . Right) then |
begin |
dT:=MyCells[i,j].Rect . Top+ 1 ; |
dL:=MyCells[i,j].Rect . Left+ 1 ; |
ExcelWorksheet1 . Cells . Item[dt,dl]:=MyCells[i,j].Text; |
end |
else |
begin |
dT:=MyCells[i,j].Rect . Top+ 1 ; |
dL:=MyCells[i,j].Rect . Left+ 1 ; |
dR:=MyCells[i,j].Rect . Right+ 1 ; |
dB:=MyCells[i,j].Rect . Bottom+ 1 ; |
//合并 |
ExcelWorksheet1 . Cells . Item[dt,dl]:=MyCells[i,j].Text; |
Ra:=ExcelWorksheet1 . Range[ExcelWorksheet1 . Cells . Item[dt,dl],ExcelWorksheet1 . Cells . Item[db,dr]]; |
Ra . MergeCells:= True ; |
end ; |
end ; |
ExcelWorkSheet1 . Columns . AutoFit; |
Finally |
ExcelWorkSheet1 . Disconnect; |
ExcelWorkBook1 . Disconnect; |
ExcelApplication1 . Disconnect; |
Ra:=Unassigned; |
end ; |
end ; |
end . |
uses |
Windows, DB; |
type |
PMyCell=^MyCell; |
MyCell= Record |
Text: String ; |
Parent:PMyCell; |
Used: Boolean ; |
Rect:TRect; |
end ; |
var |
MyCells: Array of Array of MyCell; |
R,C: Integer ; |
procedure ExportMyCell(AField:TFields); |
implementation |
procedure ExportMyCell(AField:TFields); |
//取得列标题行数 |
function GetTitleRow(ColTitle: String ): Integer ; |
var |
ii: Integer ; |
begin |
Result:= 1 ; |
for ii:= 1 to Length(ColTitle) do |
if ColTitle[ii]= '|' then Result:=Result+ 1 ; |
end ; |
Function GetMaxTitleRow(AFields:TFields): Integer ; |
var |
ii,jj: Integer ; |
begin |
Result:= 1 ; |
for ii:= 0 to AFields . Count- 1 do |
begin |
jj:=GetTitleRow(AFields[ii].DisplayLabel); |
if Result<jj then Result:=jj; |
end ; |
end ; |
procedure initMycells; |
var |
i,j: Integer ; |
begin |
SetLength(MyCells,R); |
for i:= 0 to R- 1 do |
begin |
SetLength(MyCells[i],C); |
for j:= 0 to C- 1 do |
begin |
MyCells[i,j].Text:= '' ; |
MyCells[i,j].Used:= True ; |
MyCells[i,j].Rect . Left:=j; |
MyCells[i,j].Rect . Right:=j; |
MyCells[i,j].Rect . Top:=i; |
MyCells[i,j].Rect . Bottom:=i; |
if i= 0 then MyCells[i,j].Parent:= nil |
else MyCells[i,j].Parent:=@MyCells[i- 1 ,j]; |
end ; |
end ; |
end ; |
procedure GetFieldToMycells(AFields:TFields); |
var |
i,j: Integer ; |
TmpStr: String ; |
begin |
initMycells; |
for i:= 0 to C- 1 do |
begin |
TmpStr:=AFields[i].DisplayLabel; |
j:= 0 ; |
while Pos( '|' ,TmpStr)> 0 do |
begin |
MyCells[j,i].Text:=Copy(TmpStr, 1 ,Pos( '|' ,TmpStr)- 1 ); |
MyCells[j,i].Used:= True ; |
if j<> 0 then MyCells[j,i].Parent:=@MyCells[i- 1 ,j]; |
TmpStr:=Copy(TmpStr,Pos( '|' ,TmpStr)+ 1 ,Length(TmpStr)); |
Inc(j); |
end ; |
MyCells[j,i].Text:=TmpStr; |
end ; |
end ; |
//合并过程(核心) |
procedure uniteMyCell; |
var |
i : integer ; |
procedure MoveToLastCell(MR,MC: Integer ); |
var |
i : integer ; |
begin |
for i:=MR- 1 downto 0 do |
if MyCells[i,MC].Text= '' then Continue |
else |
begin |
MyCells[R- 1 ,MC].Text:=MyCells[i,MC].Text; |
MyCells[i,MC].Text:= '' ; |
Break; |
end ; |
end ; |
procedure CheckLastRow; //检测最后行 |
var |
i: Integer ; |
begin |
for i:= 0 to C- 1 do |
if MyCells[R- 1 ,i].Text= '' then MoveToLastCell(R- 1 ,i); //移动最后一个有数据的单元格到最后一行 |
end ; |
//合并当前行 |
procedure UionCurrRowCell(CR: Integer ); |
var |
i,SC: integer ; |
function GetNextCUCell(SC: Integer ): Integer ; |
var |
i: Integer ; |
begin |
Result:=- 1 ; |
i:=SC+ 1 ; |
while (Result=- 1 ) and (i<C) do |
begin |
if not MyCells[CR,i].Used then Inc(i) |
else |
if (MyCells[CR,i].Text<> '' ) then Result:=i; |
MyCells[CR+ 1 ,i].Parent:=@MyCells[CR,i]; |
Inc(i); |
end ; |
end ; |
begin |
SC:=GetNextCUCell(- 1 ); //得到下一个可用单元 |
if SC=- 1 then Exit; |
//开始比较 |
i:=SC+ 1 ; |
while (i<c) and (SC<>- 1 ) do |
begin |
if MyCells[CR,i].Used then |
begin |
if (MyCells[CR,SC].Text=MyCells[CR,i].Text) then |
begin |
MyCells[CR,SC].Rect . Right:=i; |
MyCells[CR,i].Used:= False ; |
MyCells[CR,i].Parent:=@MyCells[CR,SC]; |
MyCells[CR+ 1 ,i].Parent:=@MyCells[CR,SC]; |
end |
else SC:=i; |
end ; |
i:=GetNextCUCell(i); |
if i=- 1 then SC:=- 1 ; |
end ; |
end ; |
procedure MoveUpCol(MR,MC: Integer ); |
var |
i : integer ; |
begin |
for i:=MR to R- 1 do |
if (MyCells[i,MC].Text= '' ) then Continue |
else |
begin |
MyCells[MR,MC].Text:=MyCells[i,MC].Text; |
MyCells[i,MC].Text:= '' ; |
Break; |
end ; |
end ; |
//检测当前行单元是否为空,为空则将有数据的列上来 |
procedure CheckCurrRow(CR: Integer ); |
var |
i : integer ; |
begin |
for i:= 0 to C- 1 do |
begin |
if (MyCells[CR,i].Used) and (MyCells[CR,i].Text= '' ) then |
begin |
MoveUpCol(CR,i); |
end ; |
end ; |
end ; |
//在范围内查找空行 |
function FindEmpty(SR: Integer {开始行} ;FindRect:TRect; var RR: Integer ): Boolean ; |
var |
i,j : integer ; |
Same: Boolean ; |
begin |
Result:= False ; |
for i:=SR to R- 1 do |
begin |
Same:= True ; |
for j:=FindRect . Left to FindRect . Right do |
if MyCells[i,j].Used and (MyCells[i,j].Text= '' ) then Continue |
else |
begin |
Same:= False ; |
Break; |
end ; |
if Same then |
begin |
RR:=i; |
Result:= True ; |
Break; |
end ; |
end ; |
end ; |
//当前行与上一行交换 |
procedure ChangeCell(CRect:TRect;RR: Integer ); |
var |
i : integer ; |
begin |
for i:= CRect . Left to CRect . Right do |
begin |
MyCells[RR,i].Text:=MyCells[RR- 1 ,i].Text; |
MyCells[RR- 1 ,i].Text:= '' ; |
end ; |
end ; |
//提升空行 |
procedure DoUpCol(CR,CC: Integer ); |
var |
i,RR: integer ; |
begin |
for i:=CR+ 2 to R- 2 do |
//在范围内查找空行,并交换行 |
if FindEmpty(i,MyCells[CR,CC].Rect,RR) then ChangeCell(MyCells[CR,CC].Rect,RR); |
end ; |
//合并列 |
procedure DoUionCell(CR,CC: Integer ); |
var |
i,RR,j: Integer ; |
begin |
for i:=CR+ 1 to R- 1 do |
begin |
if FindEmpty(i,MyCells[CR,CC].Rect,RR) then |
begin |
if RR>CR then |
begin |
MyCells[CR,CC].Rect . Bottom:=RR; |
for j:=MyCells[CR,CC].Rect . Left to MyCells[CR,CC].Rect . Right do |
begin |
MyCells[RR,j].Used:= False ; |
MyCells[RR,j].Parent:=@MyCells[CR,CC]; |
end ; |
end |
else Break; |
end else Break; |
end ; |
end ; |
//向下合并列 :) |
procedure UionCurrRowColCell(CR : integer ); |
var |
i: integer ; |
begin |
for i:= 0 to C- 1 do |
begin |
if MyCells[CR,i].Used then DoUpCol(CR,i); //提升空行 |
end ; |
for i:= 0 to C- 1 do |
begin |
if MyCells[CR,i].Used then DoUionCell(CR,i); //合并列 |
end ; |
end ; |
begin |
CheckLastRow; //检测最后行 |
for i:= 0 to R- 2 do //最后一行不管 |
begin |
UionCurrRowCell(i); //合并当前行 |
CheckCurrRow(i); //检测当前行单元是否为空,为空则将有数据的列上来 |
UionCurrRowColCell(i); //向下合并列 :) |
end ; |
end ; |
begin |
R:=GetMaxTitleRow(AField); |
C:=AField . Count; |
GetFieldToMycells(AField); |
uniteMyCell; |
end ; |
end . |