【Delphi】LibreOffice/OpenOffice Calc 試算表 API 操作

參考資料 ----
API - OpenOffice
ISO 639
ISO 3166
Creating A Border In Calc Using VB 



注意:
現在 LibreOfficex86x64 版本,若您的程式是以 delphi32 編譯,就要搭配安裝 libreoffice x86 版本。

本篇筆記以 Delphi XE6 編譯 32 位元程式,搭配 LibreOffice_5.1.4_Win_x86


 
uses
    // 主要要有 uses 這兩個
    ... System.Variants, comobj;

procedure TForm1.Button1Click(Sender: TObject);
var
    ServiceManager, StarDesktop, Document, args, Sheets, Sheet, myCol, Control,
    Range, cell, NumberFormats, LocalSettings, LineBorder,
    Border, TopLine, BottomLine, LeftLine, RightLine: Variant;
    col, row, i: integer;
    NumberFormatString: string;
    NumberFormatId: long;
begin
    ServiceManager := CreateOleObject('com.sun.star.ServiceManager');
    StarDesktop := ServiceManager.createInstance('com.sun.star.frame.Desktop');
    args := VarArrayCreate([0,1],varVariant);
    Document := StarDesktop.LoadComponentFromURL('private:factory/scalc','_blank',0, args);
    Sheets := Document.Sheets;
    
    // 第 1 張工作表的位置為 0
    // 插入一張新工作表, 參數 1 為工作表名稱, 參數 2 為工作表的位置順序
    // 當指定的位置大於現有的工作表數量時, 就是最後一張工作表
    Sheets.insertNewByName('oneMore',0);
    Sheets.insertNewByName('twoMore',4);
    Sheets.insertNewByName('threeMore',4);
    Sheets.insertNewByName('fourMore',4);
    Sheets.insertNewByName('五',4);
    Sheets.insertNewByName('六',3);

    // 移除工作表
    Sheets.removeByName('twoMore');

    // 顯示/隱藏 工作表
    Sheet := Sheets.getByName('oneMore');
    Sheet.IsVisible := false;

    Sheet := Sheets.getByName('工作表1');
    // Calc 的欄、列是以 0 為起點
    col := 0;    // 第 1 欄
    row := 9;    // 第 10 列
    Sheet.getCellByPosition(col,row).string := 'test';

    // 水平文字對齊
    // 0: STANDARD - 預設值
    // 1: LEFT - 靠左對齊
    // 2: CENTER - 置中
    // 3: RIGHT - 靠右對齊
    // 4: BLOCK - 左右對齊
    // 5: REPEAT - 重覆
    Sheet.getCellByPosition(0,0).string := '水平文字對齊-預設';
    Sheet.getCellByPosition(0,0).HoriJustify := 0;
    Sheet.getCellByPosition(1,0).string := '水平文字對齊-靠左對齊';
    Sheet.getCellByPosition(1,0).HoriJustify := 1;
    Sheet.getCellByPosition(2,0).string := '水平文字對齊-置中';
    Sheet.getCellByPosition(2,0).HoriJustify := 2;
    Sheet.getCellByPosition(3,0).string := '水平文字對齊 - 靠右對齊';
    Sheet.getCellByPosition(3,0).HoriJustify := 3;
    Sheet.getCellByPosition(4,0).string := '水平文字對齊 - 左右對齊';
    Sheet.getCellByPosition(4,0).HoriJustify := 4;
    Sheet.getCellByPosition(5,0).string := '水平文字對齊 - 重覆';
    Sheet.getCellByPosition(5,0).HoriJustify := 5;

    // 垂直文字對齊
    // 0: STANDARD - 預設值
    // 1: TOP - 靠上對齊
    // 2: CENTER - 置中
    // 3: BOTTOM - 靠下對齊
    Sheet.getCellByPosition(0,1).string := '垂直文字對齊 - 預設值';
    Sheet.getCellByPosition(0,1).VertJustify := 0;
    Sheet.getCellByPosition(1,1).string := '垂直文字對齊 - 靠上對齊';
    Sheet.getCellByPosition(1,1).VertJustify := 1;
    Sheet.getCellByPosition(2,1).string := '垂直文字對齊 - 置中';
    Sheet.getCellByPosition(2,1).VertJustify := 2;
    Sheet.getCellByPosition(3,1).string := '垂直文字對齊 - 靠下對齊';
    Sheet.getCellByPosition(3,1).VertJustify := 3;

    // 自動調整欄寬
    // 第 1 種寫法
    myCol := Sheet.Columns.getByIndex(0);
    myCol.OptimalWidth := true;
    // 第 2 種寫法
    Sheet.Columns.getByIndex(0).OptimalWidth := true;

    // 凍結窗格
    Control := Document.getCurrentController;
    Control.freezeAtPosition(0,1);

    // 合併儲存格
    Sheet.getCellByPosition(0,5).string := '合併儲存格';
    Range := Sheet.getCellRangeByName('A6:B10');
    Range.Merge(true);

    // 畫儲存格框線
    LineBorder := ServiceManager.Bridge_GetStruct('com.sun.star.table.BorderLine');
    LineBorder.Color := RGB(0, 0, 0);
    // 目前只要 OuterLineWidth 和 InnerLineWidth 同時存在
    // 就畫不出框線, 只好先 disable 其中一個
    LineBorder.OuterLineWidth := 5;
    // LineBorder.InnerLineWidth := 1;
    // LineBorder.LineDistance := 50;
    Border := ServiceManager.Bridge_GetStruct('com.sun.star.table.TableBorder');
    Border.IsTopLineValid := true;
    Border.IsBottomLineValid := true;
    Border.IsLeftLineValid := true;
    Border.IsRightLineValid := true;
    Border.TopLine := LineBorder;
    Border.BottomLine := LineBorder;
    Border.LeftLine := LineBorder;
    Border.RightLine := LineBorder;
    Range.TableBorder := Border;

    // 上框線
    TopLine := ServiceManager.Bridge_GetStruct('com.sun.star.table.BorderLine');
    TopLine.Color := RGB(255, 0, 0);
    TopLine.OuterLineWidth := 15;
    // 下框線
    BottomLine := ServiceManager.Bridge_GetStruct('com.sun.star.table.BorderLine');
    BottomLine.Color := RGB(0, 255, 0);
    BottomLine.OuterLineWidth := 15;
    // 左框線
    LeftLine := ServiceManager.Bridge_GetStruct('com.sun.star.table.BorderLine');
    LeftLine.Color := RGB(0, 0, 255);
    LeftLine.OuterLineWidth := 15;
    // 右框線
    RightLine := ServiceManager.Bridge_GetStruct('com.sun.star.table.BorderLine');
    RightLine.Color := RGB(255, 255, 0);
    RightLine.OuterLineWidth := 15;
    // 指定範圍內的水平框線
    Border.HorizontalLine := LineBorder;
    Border.IsHorizontalLineValid := true;
    // 指定範圍內的垂直框線
    Border.VerticalLine := LineBorder;
    Border.IsVerticalLineValid := true;

    Border.TopLine := TopLine;
    Border.BottomLine := BottomLine;
    Border.LeftLine := LeftLine;
    Border.RightLine := RightLine;
    Sheet.getCellRangeByName('D10:F15').TableBorder := Border;

    // 區域文字對齊
    // 0: 靠左
    // 1: 告右
    // 2: 自動折行
    // 3: 置中
    Range.ParaAdjust := 3;

    // 以名稱方式指定 儲存格
    cell := sheet.getCellRangeByName('A1');
    // Cell 背景色
    // LibreOffice 的 RGB 剛好和 Delphi 順序相反, 是 B-G-R
    cell.CellBackColor := RGB(0,0,255); // 紅色
    // Cell 字體顏色
    cell.CharColor := RGB(0,255,0); // 綠色
    // Cell 英數字體高度, 對中文字無效
    cell.CharHeight := 50;


    // 設定數字格式
    LocalSettings := ServiceManager.Bridge_GetStruct('com.sun.star.lang.Locale');
    LocalSettings.Language := 'zh';
    LocalSettings.Country := 'tw';

    NumberFormats := Document.NumberFormats;
    NumberFormatString := '#,##0.00';

    NumberFormatId := NumberFormats.queryKey(NumberFormatString, LocalSettings, True);
    if (NumberFormatId=-1) then
        NumberFormatId := NumberFormats.addNew(NumberFormatString, LocalSettings);

    // 以名稱方式指定 儲存格, 並輸入數字
    Sheet.getCellRangeByName('A15').Value := 13579;
    Sheet.getCellRangeByName('A15').NumberFormat := NumberFormatId;
    Sheet.getCellRangeByName('A16').Value := -24680;
    Sheet.getCellRangeByName('A16').NumberFormat := NumberFormatId;
    // 輸入公式
    Sheet.getCellRangeByName('A17').Formula := '=SUM(A15:A16)';