目錄    上一節  下一節

相關元件:WordApplication, WordDocument, DBLookUPCombobox, ADOConnection, ADOQuery,Button

 

Word套表

假如各位讀者,讀完了前面兩篇Delphi & Word以後,相信對Word的基本控制,已經有一定的瞭解,再來就是對於Word與資料庫所產生報表的相關運用罷了,本篇以Delphi所附的Access資料庫,與已經設計好的Word文件(可以由使用者自行設計,設計完成後再交予程式設計者),進行報表的套表。

1.      程式預覽:本篇主要是利用DBLookUPComBobox來做為資料範圍的選取(如圖25),然後分成兩個範例,利用相同的資料,對於事先已經完成的Word文件(2627)做套表的動作。

25,程式畫面

26Word文件一

27,佈滿整頁的Word文件

2.      資料庫設計:本程式為Master-Detail的資料庫,兩個ADOQuerySQL語法如下

主檔(Master)請注意中間的空白為用來填入DBLookUPCombobox選取的內容,假如使用未選取,怎為空白,表示選取全部,此為筆者報表程式設計的方式,各位讀者可以參考使用

select a.OrderNo,a.CustNo,a.empno,c.LastName,c.FirstName,a.SaleDate,a.ShipDate,a.ShipVIA,a.Freight,b.Company,

    b.Addr1,b.Addr2,b.City,b.State,b.Zip,b.Country

from orders a,CUSTOMER b,EMPLOYEE c

where a.custno=b.custno and a.empno=c.empno

 

 

 

order by a.orderNO

次檔(Detail)

select a.PartNo,a.OrderNO,b.Description,a.Qty,b.ListPrice,a.Discount,a.qty*b.ListPrice*(100-a.discount)/100 as amount

from ITEMS a,PARTS b

where a.PartNO=b.PartNO and a.orderno=:orderNO

3.      程式設計:

a.       當使用者選取起始編號與終止編號時,紀錄選取的資料

procedure TForm1.DBLookupComboBox1CloseUp(Sender: TObject);

begin

   qs1:=DBLookupComboBox1.Text;

end;

 

procedure TForm1.DBLookupComboBox2CloseUp(Sender: TObject);

begin

   qs2:=DBLookupComboBox2.Text;

end;

b.      按下InVoice1 Button(使用Invoice.doc)

procedure TForm1.Button1Click(Sender: TObject);

var Template,ItemIndex,_Type:OleVariant;

    s:string;

    i,j,k:integer;

    sum:real;

begin

   _Type:=wdSectionBreakNextPage;

   s:=extractfilepath(application.ExeName)+'invoice.doc';

   if Fileexists(s) then

   begin

//開啟Word檔案

      Template:=s;

      WordApplication1.Documents.Open(template,EmptyParam,EmptyParam,EmptyParam,EmptyParam,

            EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam);

//第一個Word檔案連接,對於Word來說,新產生的檔案ItemIndex再第一個

      ItemIndex:=1;

      WordDocument1.ConnectTo(WordApplication1.Documents.Item(ItemIndex));

//顯示Word檔案,假如已經有其他word文件開啟,則不會有動作

      WordApplication1.Visible:= True;

//先將整個Word文件複製:在進行Word多頁套表設計時,必須先將Word表格複製,當超過一頁時,再將表格貼上,不過為避免上下頁表格連接,兩個表格間必須有一空白行,以免造成Word視為一個表格,同時也造成版面的問題,因此,在程式開始時,將Word表格先剪下,使整個Word文件,剩下變成一個Enter,在程式開始後,再將表格貼上,如此整個Word文件會多出一個Enter,在程式結束前,將其刪除。

      WordDocument1.Range.Select;

      WordDocument1.Range.Cut;

//查詢條件輸入

      ADOQuery1.Active:=false;

      if qs1='' then

         ADOQuery1.SQL.Strings[3]:=''

      else

         ADOQuery1.SQL.Strings[3]:='  and a.OrderNo>='+qs1;

      if qs2='' then

         ADOQuery1.SQL.Strings[4]:=''

      else

         ADOQuery1.SQL.Strings[4]:='  and a.OrderNo<='+qs2;

      ADOQuery1.active:=true;

      ADOQuery2.Active:=true;

      ADOQuery1.First;

      i:=0;  //table

      while not ADOQuery1.Eof do

      begin

//將表格貼上

         Worddocument1.Range.Characters.Last.select;

         Worddocument1.Range.Characters.Last.paste;

         i:=i+1;

         if i>1 then  //插入分頁符號

         begin

            WordDocument1.Tables.Item(i).Select;

            WordApplication1.Selection.InsertBreak(_Type);

         end;

         WordDocument1.Tables.Item(i).Cell(1,1).Select;

//用置換的方法,置換Master的資料,repl函數,請參考後面說明

         repl('Company_name',ADOQuery1.fieldbyname('company').asstring);

         repl('Address1',ADOQuery1.fieldbyname('Addr1').asstring+','+ADOQuery1.fieldbyname('Addr2').asstring);

         repl('Address2',ADOQuery1.fieldbyname('City').asstring+','+ADOQuery1.fieldbyname('State').asstring+','+

                  ADOQuery1.fieldbyname('Zip').asstring);

         repl('Address3',ADOQuery1.fieldbyname('Country').asstring);

//固定的Master表格資料

         WordDocument1.Tables.Item(i).Cell(3,1).Range.Text:=ADOQuery1.fieldbyname('OrderNO').asstring;

         WordDocument1.Tables.Item(i).Cell(3,2).Range.Text:=ADOQuery1.fieldbyname('CustNO').asstring;

         WordDocument1.Tables.Item(i).Cell(3,3).Range.Text:=ADOQuery1.fieldbyname('LastName').asstring+

                  ' '+ADOQuery1.fieldbyname('FirstName').asstring;

         WordDocument1.Tables.Item(i).Cell(3,4).Range.Text:=ADOQuery1.fieldbyname('SaleDate').asstring;

         WordDocument1.Tables.Item(i).Cell(3,5).Range.Text:=ADOQuery1.fieldbyname('ShipDate').asstring;

         WordDocument1.Tables.Item(i).Cell(3,6).Range.Text:=ADOQuery1.fieldbyname('ShipVia').asstring;

         j:=5;

         sum:=0;

//Detail資料填入

         While not ADOQuery2.Eof do

         begin

            WordDocument1.Tables.Item(i).Cell(j,1).Range.Text:=ADOQuery2.fieldbyname('PartNO').asstring;

            WordDocument1.Tables.Item(i).Cell(j,2).Range.Text:=ADOQuery2.fieldbyname('Description').asstring;

            WordDocument1.Tables.Item(i).Cell(j,3).Range.Text:=ADOQuery2.fieldbyname('Qty').asstring;

            WordDocument1.Tables.Item(i).Cell(j,4).Range.Text:=formatfloat('###,###.#0',

                  ADOQuery2.fieldbyname('ListPrice').asfloat);

            WordDocument1.Tables.Item(i).Cell(j,5).Range.Text:=formatfloat('###,###.##',

                  ADOQuery2.fieldbyname('Discount').AsFloat);

            WordDocument1.Tables.Item(i).Cell(j,6).Range.Text:=formatfloat('###,###.#0',

                  ADOQuery2.fieldbyname('amount').AsFloat);

            sum:=sum+ADOQuery2.fieldbyname('amount').AsFloat;

            WordDocument1.Tables.Item(i).Cell(j,6).select;

            j:=j+1;

            ADOQuery2.Next;

            if not ADOQuery2.Eof then

               insertoneline;  //插入一行

         end;

         WordDocument1.Tables.Item(i).Cell(j,2).Range.Text:=formatfloat('###,###.#0',sum);

         WordDocument1.Tables.Item(i).Cell(j+1,2).Range.Text:=formatfloat('###,###.#0',

                  ADOQuery1.fieldbyname('Freight').AsFloat);

         WordDocument1.Tables.Item(i).Cell(j+2,2).Range.Text:=formatfloat('###,###.#0',

                  sum+ADOQuery1.fieldbyname('Freight').AsFloat);

         ADOQuery1.Next;

      end;

//刪除最號的enter

      WordDocument1.Range.Characters.Last.Delete(emptyparam,ItemIndex);

      WordDocument1.Disconnect;

      WordApplication1.Disconnect;

      ADOQuery1.Active:=false;

      ADOQuery1.SQL.Strings[3]:='';

      ADOQuery1.SQL.Strings[4]:='';

      ADOQuery1.Active:=true;

   end else

   begin

      showmessage('無法找到'+s);

   end;

end;

請注意,在以上的方式中,筆者並未控制當Detail資料超過一頁時的結果

c.       按下InVoice2 Button(使用Invoice2.doc)

procedure TForm1.Button2Click(Sender: TObject);

var Template,ItemIndex:OleVariant;

    s:string;

    i,j,k:integer;

    sum:real;

begin

   s:=extractfilepath(application.ExeName)+'invoice2.doc';

   if Fileexists(s) then

   begin

      Template:=s;

      WordApplication1.Documents.Open(template,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,

            EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam);

      ItemIndex:=1;

      WordDocument1.ConnectTo(WordApplication1.Documents.Item(ItemIndex));

      WordApplication1.Visible:= True;

      WordDocument1.Range.Select;

      WordDocument1.Range.Cut;

      ADOQuery1.Active:=false;

      if qs1='' then

         ADOQuery1.SQL.Strings[3]:=''

      else

         ADOQuery1.SQL.Strings[3]:='  and a.OrderNo>='+qs1;

      if qs2='' then

         ADOQuery1.SQL.Strings[4]:=''

      else

         ADOQuery1.SQL.Strings[4]:='  and a.OrderNo<='+qs2;

      ADOQuery1.active:=true;

      ADOQuery2.Active:=true;

      ADOQuery1.First;

      i:=0;  //table

      while not ADOQuery1.Eof do

      begin

         Worddocument1.Range.Characters.Last.select;

         Worddocument1.Range.Characters.Last.paste;

         i:=i+1;

         WordDocument1.Tables.Item(i).Cell(1,1).Select;

         repl('Company_name',ADOQuery1.fieldbyname('company').asstring);

         repl('Address1',ADOQuery1.fieldbyname('Addr1').asstring+','+ADOQuery1.fieldbyname('Addr2').asstring);

         repl('Address2',ADOQuery1.fieldbyname('City').asstring+','+ADOQuery1.fieldbyname('State').asstring+','+

                  ADOQuery1.fieldbyname('Zip').asstring);

         repl('Address3',ADOQuery1.fieldbyname('Country').asstring);

         WordDocument1.Tables.Item(i).Cell(3,1).Range.Text:=ADOQuery1.fieldbyname('OrderNO').asstring;

         WordDocument1.Tables.Item(i).Cell(3,2).Range.Text:=ADOQuery1.fieldbyname('CustNO').asstring;

         WordDocument1.Tables.Item(i).Cell(3,3).Range.Text:=ADOQuery1.fieldbyname('LastName').asstring+

                  ' '+ADOQuery1.fieldbyname('FirstName').asstring;

         WordDocument1.Tables.Item(i).Cell(3,4).Range.Text:=ADOQuery1.fieldbyname('SaleDate').asstring;

         WordDocument1.Tables.Item(i).Cell(3,5).Range.Text:=ADOQuery1.fieldbyname('ShipDate').asstring;

         WordDocument1.Tables.Item(i).Cell(3,6).Range.Text:=ADOQuery1.fieldbyname('ShipVia').asstring;

         j:=5;

         sum:=0;

         While not ADOQuery2.Eof do

         begin

            WordDocument1.Tables.Item(i).Cell(j,1).Range.Text:=ADOQuery2.fieldbyname('PartNO').asstring;

            WordDocument1.Tables.Item(i).Cell(j,2).Range.Text:=ADOQuery2.fieldbyname('Description').asstring;

            WordDocument1.Tables.Item(i).Cell(j,3).Range.Text:=ADOQuery2.fieldbyname('Qty').asstring;

            WordDocument1.Tables.Item(i).Cell(j,4).Range.Text:=formatfloat('###,####.#0',

                        ADOQuery2.fieldbyname('ListPrice').asfloat);

            WordDocument1.Tables.Item(i).Cell(j,5).Range.Text:=formatfloat('###,####.##',

                        ADOQuery2.fieldbyname('Discount').AsFloat);

            WordDocument1.Tables.Item(i).Cell(j,6).Range.Text:=formatfloat('###,####.#0',

                        ADOQuery2.fieldbyname('amount').AsFloat);

            sum:=sum+ADOQuery2.fieldbyname('amount').AsFloat;

            j:=j+1;

            ADOQuery2.Next;

         end;

         WordDocument1.Tables.Item(i).Cell(30,2).Range.Text:=formatfloat('###,####.#0',sum);

         WordDocument1.Tables.Item(i).Cell(31,2).Range.Text:=formatfloat('###,####.#0',

                  ADOQuery1.fieldbyname('Freight').AsFloat);

         WordDocument1.Tables.Item(i).Cell(32,2).Range.Text:=formatfloat('###,####.#0',

                  sum+ADOQuery1.fieldbyname('Freight').AsFloat);

         ADOQuery1.Next;

      end;

      WordDocument1.Range.Characters.Last.Delete(emptyparam,ItemIndex);

      WordDocument1.Disconnect;

      WordApplication1.Disconnect;

      ADOQuery1.Active:=false;

      ADOQuery1.SQL.Strings[3]:='';

      ADOQuery1.SQL.Strings[4]:='';

      ADOQuery1.Active:=true;

   end else

   begin

      showmessage('無法找到'+s);

   end;

end;

d.      repl函數

procedure TForm1.repl(source,repl_text:string);

var _Text,_MatchCase,_MatchWholeWord,_MatchWildcards,_MatchSoundsLike,

    _MatchAllWordForms,_Forward,_Wrap,_Format,_ReplaceWith,_Replace,

    _MatchKashida,_MatchDiacritics,_MatchAlefHamza,_MatchControl:OleVariant;

begin

   WordApplication1.Selection.Find.ClearFormatting;

   _Text :=source;

   _MatchCase := False;

   _MatchWholeWord := False;

   _MatchWildcards := False;

   _MatchSoundsLike := False;

   _MatchAllWordForms:=EmptyParam;

   _Forward := True;

   _Wrap := wdFindContinue;

   _Format := False;

   _Replace:=wdReplaceOne;

   _ReplaceWith:=repl_text;

   _MatchKashida:=EmptyParam;

   _MatchDiacritics:=EmptyParam;

   _MatchAlefHamza:=EmptyParam;

   _MatchControl:=EmptyParam;

   WordApplication1.Selection.Find.Execute(_Text,_MatchCase,_MatchWholeWord,

      _MatchWildcards,_MatchSoundsLike,_MatchAllWordForms,_Forward,_Wrap,

      _Format,_ReplaceWith,_Replace,_MatchKashida,_MatchDiacritics,

      _MatchAlefHamza,_MatchControl);

end;

e.       插入一行函數

procedure TForm1.insertoneLine;

var _NumberRows:OleVariant;

begin

   _NumberRows:=1;

   WordApplication1.Selection.InsertRowsBelow(_NumberRows);

end;

目錄        上一節    下一節