全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:11011
推到 Plurk!
推到 Facebook!

Dbgrid 記錄匯出至 openoffice.calc

 
kadee
高階會員


發表:11
回覆:141
積分:165
註冊:2002-03-20

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-12-08 12:17:13 IP:220.134.xxx.xxx 未訂閱
分享一個function,可以將Dbgrid 記錄匯出至 openoffice.calc. 希望可以推廣ooo的應用  
 
function gfSendToOpenOffice(poGrid: tdbgrid; psTitle: string = '';
  psFilename: string = ''): boolean;
var
  i, liR0, liRow, liCol: integer;
  lCol: TColumn;
  lfield: TField;
  objServiceManager,
    objDesktop,
    oDocument,
    osheets,
    osheet: OleVariant;
  objDocName,
    objDocParam,
    objDocNum,
    objParam: variant;
  AEVENT: TDataSetNotifyEvent;
  procedure setsheetvalue(ic, ir: integer; objsheet: OleVariant;
    psvalue: string);
  begin
    objsheet.getCellByPosition(ic, ir).string := psvalue;
  end;
  procedure setsheetint(ic, ir: integer; objsheet: OleVariant;
    psvalue: string);
  begin
    objsheet.getCellByPosition(ic, ir).Formula := '='   psvalue;
  end;
begin
  aEvent := poGrid.DataSource.DataSet.AfterScroll;
  Result := true;
  try
    poGrid.DataSource.DataSet.AfterScroll := nil;
    poGrid.DataSource.DataSet.DisableControls;
    try
      // The service manager is always the starting point
      // If there is no office running then an office is started up
      objServiceManager := CreateOLEObject('com.sun.star.ServiceManager');
      // Create the Desktop
      objDesktop :=
        objServiceManager.createInstance
        ('com.sun.star.frame.Desktop');
      // Open a new empty writer document
      objDocName := 'private:factory/scalc';
      objDocParam := '_blank';
      objDocNum := 0;
      objParam := VarArrayCreate([0, 1], VarVariant);
      objParam[0] := ''; // .Name = ''
      objParam[1] := 0; // .Value = 0
      oDocument := objDesktop.loadComponentFromURL
        (objDocName, objDocParam, 0, VarArrayOf([]));
      oSheets := oDocument.Sheets;
      if oSheets.hasByName('工作表1') then
        oSheet := oSheets.getByName('工作表1')
      else
        oSheet := oDocument.createInstance
          ('com.sun.star.sheet.Spreadsheet');
      liCol := 0;
      liR0 := 0; //row
      if psTitle <> '' then
      begin
        //表單標題
        setsheetvalue(0, 0, osheet, psTitle);
        inc(lir0);
      end;          for i := 0 to poGrid.Columns.Count - 1 do
      begin
        lCol := poGrid.Columns[i];
        lfield := lcol.Field;
        if lfield = nil then
          continue;
        //寬度縮太小之欄位不轉出
        if (lCol.Width < 15) then
          continue;
        //轉入欄位標題
        liRow := liR0   1;
        setsheetvalue(liCol, liRow, osheet, lfield.DisplayLabel);
        //轉入欄位之資料
        poGrid.DataSource.DataSet.first;
        inc(liRow);
        while not poGrid.DataSource.DataSet.eof do
        begin
          if (not lfield.isnull) then
          begin
            case lfield.DataType of
              ftString:
                if (lfield.asstring <> '') then
                  setsheetvalue(liCol, liRow, osheet, lfield.AsString);                  ftBCD, ftInteger, ftFloat, ftCurrency, ftSmallint:
                setsheetint(liCol, liRow, osheet, lfield.asstring);                  ftDate, ftTime, ftDateTime:
                setsheetvalue(liCol, liRow, osheet, lfield.AsString);                end; //case
          end; //isnull
          poGrid.DataSource.DataSet.Next;
          inc(liRow);
        end; //while }
        inc(liCol);
      end; //for
      result := true;
    except
      gpmsg('無法啟動 open-office !!', false);
      if DebugHook > 0 then
        raise;
    end; //try
  finally
    poGrid.DataSource.DataSet.AfterScroll := aevent;
    poGrid.DataSource.DataSet.EnableControls;
  end;
end;    
Kadee_BigRed
------
Kadee/BigRed Ent.
www.tw165.com
bugmans
高階會員


發表:95
回覆:322
積分:188
註冊:2003-04-12

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-03-21 22:37:47 IP:218.167.xxx.xxx 未訂閱
我在OpenOffice 1.1.2開始接觸這個軟體,雖然功能不比微軟的Office強
(在1.1.x的版本中,表格的儲存格高度無法用滑鼠調整,只能利用換行來調整,
或是開啟含中文字的檔案會出現方塊字,這些問題在OpenOffice2.0已有大幅度
的改善),但這個軟體所強調開放自由的精神卻是讓我非常認同的,我也嘗試著
用OpenOffice進行簡單的文書處理,後來開始接觸OpenOffice的Macro和API,我
回到Delphi K.Top搜尋是否有相關的討論,很可惜的是有關於OpenOffice程式
設計的只有kadee所發表的"Dbgrid 記錄匯出至openoffice.calc"(也就是各位
看到的這篇),於是我將近日所研究的結果發表出來,以期達到拋磚引玉的效果
因為我比較常用Writer(相對於微軟的Word)寫報告,所以之後的程式碼都是針對
Writer來說明,在BCB6要多加
[code cpp]
#include
[/code]

出處http://delphi.ktop.com.tw/topic.php?TOPIC_ID=42389

[code cpp]
void __fastcall TForm1::FormCreate(TObject *Sender)
{
//開啟空白的Writer檔案
Variant vService = CreateOleObject("com.sun.star.ServiceManager");
Variant vDesktop = vService.OleFunction("createInstance", "com.sun.star.frame.Desktop");
Variant vEmptyParam(OPENARRAY(int, (0, -1)), varInteger);
Variant vDocument = vDesktop.OleFunction("loadComponentFromURL", "private:factory/swriter", "_blank", 0, vEmptyParam);

//插入文字
//出處http://mail.python.org/pipermail/python-win32/2002-May/000359.html
Variant vText = vDocument.OleFunction("GetText");
Variant vCursor = vText.OleFunction("CreateTextCursor");
vText.OleFunction("insertString",vCursor,"測試",false);

//插入表格
//出處:StarSuite 7 程式設計手冊 106 107頁
Variant vTable = vDocument.OleFunction("createInstance","com.sun.star.text.TextTable");
vTable.OleFunction("initialize",5,4);
vText.OleFunction("insertTextContent",vCursor,vTable,false);

//在儲存格中插入文字
Variant vCell=vTable.OleFunction("getCellByName","B2");
vCell.OlePropertySet("String","儲存格文字");

//改變表格背景顏色
//出處:StarSuite 7 程式設計手冊 108頁
Variant vRows = vTable.OleFunction("getRows");
Variant vRow;
for(int i=0;i<2;i )
//出處http://www.oooforum.org/forum/viewtopic.phtml?t=14326
Variant Cursor =vTable.OleFunction("createCursorByCellName","A1");
Cursor.OleFunction("splitrange",3,false);

//插入圖片
Variant vImage = vDocument.OleFunction("createInstance","com.sun.star.text.GraphicObject");
vImage.OlePropertySet("GraphicURL","file:///C:/WINNT/Soap Bubbles.bmp");
vText.OleFunction("insertTextContent",vCursor,vImage,false);

//儲存檔案
vDocument.OleFunction("storeToURL","file:///c:/test.odt",vEmptyParam);
//vDocument.OleFunction("Close",true);
}
[/code]


以上幾個範例無法滿足實作上的需求,我再介紹幾個參考文件讓各位在學習OpenOffice API
時更加順手 StarSuite 7 Office Suite - Basic 程式設計手冊(繁體中文)
http://docs-pdf.sun.com/817-3928/817-3928.pdf
雖然是StarSuite但是OpenOffice也是同樣適用,從第五章開始開始介紹API,裡面的範例非常
淺顯易懂,更何況是繁體中文的內容,非常建議仔細閱讀 OpenOffice.org Macros and API論壇
http://www.oooforum.org/forum/viewforum.phtml?f=9
這裡是討論OpenOffice API最熱鬧的地方,我反倒覺得假如有關API的問題應該到這裡來問,
到Delphi K.Top發問可能會無人回應 http://www.pitonyak.org/AndrewMacro.sxw
Andrew Pitonyak針對論壇上常發問的問題作個整理
例如上面的範例中插入圖片的程式碼

[code cpp]
Variant vImage = vDocument.OleFunction("createInstance","com.sun.star.text.GraphicObject");
vImage.OlePropertySet("GraphicURL","file:///C:/WINNT/Soap Bubbles.bmp");
vText.OleFunction("insertTextContent",vCursor,vImage,false);
[/code]

這個方法有個缺點是圖不會包在文件檔中,在7.15.3 Can I embed or link a graphics object?
有提到解決方法
出處:http://www.oooforum.org/forum/viewtopic.phtml?t=11183
OpenOffice SDK(英文版)
http://www.openoffice.org/dev_docs/source/sdk/
StarSuite7 SDK(簡體中文版)
http://192.18.97.244/ECom/EComTicketServlet/BEGINBD9B3C6D81227F09EDE32F1E5350852D/
98986803/768474195/1/359978/467702/768474195/2ts /westCoastFSEND/SOSDK-7-G-F/
SOSDK-7-G-F:8/StarSuite7_SDK_zh-CN.zip
其實StarSuite 7 的SDK和OpenOffice SDK內容是相同的,但建議下載StareSutie SDK,因為
StarSuite SDK有簡體中文的版本,但OpenOffice SDK沒有
編輯記錄
bugmans 重新編輯於 2009-03-21 08:27:50, 註解 無‧
bugmans 重新編輯於 2009-03-21 08:30:44, 註解 無‧
bugmans 重新編輯於 2009-03-21 08:37:06, 註解 無‧
bugmans 重新編輯於 2009-03-21 08:46:38, 註解 無‧
a903
一般會員


發表:5
回覆:13
積分:3
註冊:2003-08-27

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-05-18 16:25:20 IP:202.39.xxx.xxx 未訂閱
使用 gfSendToOpenOffice 在 Call setsheetvalue(0, 0, osheet, psTitle) 出現 com.sun.star.uno.RunTimeException 請問如何解
adson
一般會員


發表:0
回覆:2
積分:0
註冊:2007-12-17

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-12-18 16:38:42 IP:61.177.xxx.xxx 訂閱
樓主,您好.
首先我是一個新手,
公司準備推openoffice了,可是我之前開發的delphi中有些轉檔程式(例如,將資料庫中數據轉成Excel檔), 但是轉成openoffice的工作表我沒有做過, 昨天看到你的這個帖子,幫了我一個大忙啊 .
既然從資料庫中可以將數據轉換成openoffice工作表, 我想應該也可以通過程式將工作表中的數據upload到資料庫中吧, 這個問題已經困擾了我好幾天了,懇請樓主幫忙. 不勝感激!!!!!!
------
年少輕狂,幸福時光
kadee
高階會員


發表:11
回覆:141
積分:165
註冊:2002-03-20

發送簡訊給我
#5 引用回覆 回覆 發表時間:2007-12-18 17:24:09 IP:59.127.xxx.xxx 未訂閱
目前網路上還沒有找到從delphi直接連接 OOO的方式,
建議:在ooo calc中存成 excel,再用ADO去連,應該是目前的辦法。
------
Kadee/BigRed Ent.
www.tw165.com
adson
一般會員


發表:0
回覆:2
積分:0
註冊:2007-12-17

發送簡訊給我
#6 引用回覆 回覆 發表時間:2007-12-19 09:04:51 IP:61.177.xxx.xxx 訂閱
不好意思, 您說的在ooo calc中存成 excel,再用ADO去連, 我沒能理解.
您的意思是說在calc中將做好的資料保存為excel格式嗎?

之前用excel上傳資料的時候,程序是這樣的: 在上傳畫面中,使用opendialog先打開excel檔案的, 點上傳按鈕後,即可將各欄位的內容保存到資料庫表所對應的各個欄位中.

但是現在openoffice時, 我就仿照您帖子上從dbgrid中匯入openoffice工作表這個程式,
還是不可以的, 關鍵我覺得其中的一些method 不知道, 這個和 MS Office是不一樣的. 運行的時候 總是提示method not surpported variant .
------
年少輕狂,幸福時光
Reiji
初階會員


發表:30
回覆:57
積分:32
註冊:2008-06-26

發送簡訊給我
#7 引用回覆 回覆 發表時間:2010-11-05 11:53:50 IP:61.219.xxx.xxx 訂閱
 不好意思,最近公司也在推OO.o
但是遇到了一個問題
那就是TDBGrid中有MEMO欄位時,轉出至OO.o會空白(EXCEL不會)
不曉得有沒有前輩也有遇過?
該如何解決?


結果剛發問完就發現我眼睛太大了,沒找到問題出處
在此PO文自答,當筆記

在程式其中一段加入需要轉出的格式即可

------
永遠都是新手
編輯記錄
Reiji 重新編輯於 2010-11-05 01:07:30, 註解 回答自己的問題‧
Reiji 重新編輯於 2010-11-05 01:10:32, 註解 無‧
Reiji 重新編輯於 2010-11-05 01:11:53, 註解 無‧
Reiji 重新編輯於 2010-11-05 01:12:31, 註解 重新編輯張貼格式‧
Reiji
初階會員


發表:30
回覆:57
積分:32
註冊:2008-06-26

發送簡訊給我
#8 引用回覆 回覆 發表時間:2010-11-05 12:04:47 IP:61.219.xxx.xxx 訂閱
過了這麼久,大概也研究出來了吧?
但當作是筆記,我就在此回覆好了

我遇到這個問題是
oDocument := objDesktop.loadComponentFromURL
在程式跑到setsheetvalue中的osheet無法取得目標
解決的方法就是在===================引 用 a903 文 章===================
使用 gfSendToOpenOffice 在 Call setsheetvalue(0, 0, osheet, psTitle) 出現 com.sun.star.uno.RunTimeException 請問如何解

------
永遠都是新手
anchor
一般會員


發表:0
回覆:3
積分:0
註冊:2013-03-27

發送簡訊給我
#9 引用回覆 回覆 發表時間:2013-03-27 21:15:13 IP:59.127.xxx.xxx 訂閱
我使用 Delphi XE & Openoffice 3.3板,RUN 至以下程式,發生"錯誤變數類型" 要如何修正

oDocument := objDesktop.loadComponentFromURL
(objDocName, objDocParam, 0, VarArrayOf([]));

Reiji
初階會員


發表:30
回覆:57
積分:32
註冊:2008-06-26

發送簡訊給我
#10 引用回覆 回覆 發表時間:2013-03-27 21:59:35 IP:122.117.xxx.xxx 訂閱
www.openoffice.org/api/docs/common/ref/com/sun/star/frame/XComponentLoader.html
objDocName, objDocParam宣告的型態、值的型態
依原PO的例子來說
variant,值為字串:
'private:factory/scalc'
'_blank'

也就是
(,

------
永遠都是新手
anchor
一般會員


發表:0
回覆:3
積分:0
註冊:2013-03-27

發送簡訊給我
#11 引用回覆 回覆 發表時間:2013-03-28 19:34:52 IP:59.127.xxx.xxx 訂閱
我是將整個Function  COPY 下來,其中有修改某些行

1. 在uses 增加 ,ComObj ==>因為此函數系統不認的CreateOLEObject('com.sun.star.ServiceManager');

2. 這一行 ,因為無法執行 "gpmsg('無法啟動 open-office !!', false);" 改為 "showmessage( '無法啟動 open-office !!');"

接下來button 鍵,下的参數為==> gfSendToOpenOffice(tdbgrid1,'','');
其中tdbgrid1 指我的dbgrid 的物件名,

然後開始執行就出現錯誤訊息
Reiji
初階會員


發表:30
回覆:57
積分:32
註冊:2008-06-26

發送簡訊給我
#12 引用回覆 回覆 發表時間:2013-03-29 09:46:20 IP:61.219.xxx.xxx 訂閱
 可以的話,提供你loadComponentFromURL前面全部的程式碼(從宣告開始)
還有後三行程式碼

如果以程式邏輯來說應該是不會有問題
------
永遠都是新手
anchor
一般會員


發表:0
回覆:3
積分:0
註冊:2013-03-27

發送簡訊給我
#13 引用回覆 回覆 發表時間:2013-03-29 19:25:17 IP:59.127.xxx.xxx 訂閱
以下是我程式內容,  麻煩你,謝謝


unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Grids, DBGrids, DB, DBTables,ComObj;
type
TForm1 = class(TForm)
Button1: TButton;
Table1: TTable;
DataSource1: TDataSource;
tdbgrid1: TDBGrid;
Button2: TButton;
Table1subjno: TIntegerField;
Table1subjnm: TStringField;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
//Form2: TForm2;
implementation
uses Unit2;
{$R *.dfm}
function gfSendToOpenOffice(poGrid: tdbgrid; psTitle: string = '';
psFilename: string = ''): boolean;
var
i, liR0, liRow, liCol: integer;
lCol: TColumn;
lfield: TField;
objServiceManager,
objDesktop,
oDocument,
osheets,
osheet: OleVariant;
objDocName,
objDocParam,
objDocNum,
objParam: variant;
AEVENT: TDataSetNotifyEvent;
procedure setsheetvalue(ic, ir: integer; objsheet: OleVariant;
psvalue: string);
begin
objsheet.getCellByPosition(ic, ir).string := psvalue;
end;
procedure setsheetint(ic, ir: integer; objsheet: OleVariant;
psvalue: string);
begin
objsheet.getCellByPosition(ic, ir).Formula := '=' psvalue;
end;
begin
aEvent := poGrid.DataSource.DataSet.AfterScroll;
Result := true;
try
poGrid.DataSource.DataSet.AfterScroll := nil;
poGrid.DataSource.DataSet.DisableControls;
try
// The service manager is always the starting point
// If there is no office running then an office is started up
objServiceManager := CreateOLEObject('com.sun.star.ServiceManager');
// Create the Desktop
objDesktop :=
objServiceManager.createInstance
('com.sun.star.frame.Desktop');
// Open a new empty writer document
objDocName := 'private:factory/scalc';
objDocParam := '_blank';
objDocNum := 0;
objParam := VarArrayCreate([0, 1], VarVariant);
objParam[0] := ''; // .Name = ''
objParam[1] := 0; // .Value = 0
oDocument := objDesktop.loadComponentFromURL
(objDocName, objDocParam, 0, VarArrayOf([]));
oSheets := oDocument.Sheets;
if oSheets.hasByName('工作表1') then
oSheet := oSheets.getByName('工作表1')
else
oSheet := oDocument.createInstance
('com.sun.star.sheet.Spreadsheet');
liCol := 0;
liR0 := 0; //row
if psTitle <> '' then
begin
//表單標題
setsheetvalue(0, 0, osheet, psTitle);
inc(lir0);
end;
for i := 0 to poGrid.Columns.Count - 1 do
begin
lCol := poGrid.Columns[i];
lfield := lcol.Field;
if lfield = nil then
continue;
//寬度縮太小之欄位不轉出
if (lCol.Width < 15) then
continue;
//轉入欄位標題
liRow := liR0 1;
setsheetvalue(liCol, liRow, osheet, lfield.DisplayLabel);
//轉入欄位之資料
poGrid.DataSource.DataSet.first;
inc(liRow);
while not poGrid.DataSource.DataSet.eof do
begin
if (not lfield.isnull) then
begin
case lfield.DataType of
ftString:
if (lfield.asstring <> '') then
setsheetvalue(liCol, liRow, osheet, lfield.AsString);
ftBCD, ftInteger, ftFloat, ftCurrency, ftSmallint:
setsheetint(liCol, liRow, osheet, lfield.asstring);
ftDate, ftTime, ftDateTime:
setsheetvalue(liCol, liRow, osheet, lfield.AsString);
end; //case
end; //isnull
poGrid.DataSource.DataSet.Next;
inc(liRow);
end; //while }
inc(liCol);
end; //for
result := true;
except
//gpmsg('無法啟動 open-office !!', false);
showmessage( '無法啟動 open-office !!');
if DebugHook > 0 then
raise;
end; //try
finally
poGrid.DataSource.DataSet.AfterScroll := aevent;
poGrid.DataSource.DataSet.EnableControls;
end;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
Form2 := TForm2.Create(Application);
Form2.Show;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
gfSendToOpenOffice(tdbgrid1,'','');
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
end;
end.
Reiji
初階會員


發表:30
回覆:57
積分:32
註冊:2008-06-26

發送簡訊給我
#14 引用回覆 回覆 發表時間:2013-04-01 11:12:44 IP:61.219.xxx.xxx 訂閱
OO.o 3.4.1+Delphi5 測試過,程式沒有問題
如果有可能的話,大概是Delphi版本支援的問題了吧?
------
永遠都是新手
系統時間:2024-04-18 23:04:38
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!