RubyからLibreOfficeのCalcを操作します。Windows上で動作します。
動作確認したバージョン
Rubyのバージョン:ruby 3.1.2p20 (x64)
Calc (LibreOffice) のバージョン:7.2.7.2(x64)
calcUtil.rbのダウンロード(calcUtil_v100.7z)
CalcUtilクラス
# coding: utf-8
# calc操作の例
require 'win32ole'
require './calcUtil'
require './wincons'
arfruits = [ [ "りんご", 3500 ],
[ "なし", 3120 ],
[ "みかん", 2950 ],
[ "バナナ", 2800 ]
]
calcUtld = CalcUtilt.new();
cons = Console.new(__ENCODING__)
servmng = WIN32OLE.new("com.sun.star.ServiceManager")
desktop = servmng.createInstance("com.sun.star.frame.Desktop")
# ------- 既存のcalcファイルを開く場合
#sfname = __dir__.encode("utf-8") + "/calcf例1.ods" # ファイル名
#sfname = "file:///" + sfname.gsub("¥¥","/")
#odoc = desktop.loadComponentfromUrl(sfname, '_blank', 0, [])
# ------- 新規で起動
odoc = desktop.loadComponentfromUrl("private:factory/scalc", "_blank", 0, [])
sheets = odoc.getSheets() # シートオブジェクト
nshnm = "果物" # 新シート名
if !(sheets.hasByName(nshnm)) # 存在するか?
sheets.insertNewByName(nshnm,0) # シート追加 0:追加する位置
end
sheet = sheets.getByName(nshnm) # 追加シート選択
odoc.CurrentController().setActiveSheet(sheet) # 追加シートをアクテイブに(前面表示)
shnm = sheet.Name # シート名取得
print "シート名:" + shnm.encode("utf-8") + "¥r¥n"
ix = 'B'.ord - 'A'.ord; iy = 2 # B3
sheet.getCellByposition(ix, iy).String = "品名"
sheet.getCellByposition(ix + 1, iy).String = "金額"
oCell = sheet.getCellRangeByPosition(ix, iy, ix + 1, iy) # "B3:C3"
oCell.CellBackColor = calcUtld.RGB(0xff, 0, 0) # バック色赤
oCell.charColor = calcUtld.RGB(0xff, 0xff, 0xff) # 文字色白
oCell.HoriJustify = CalcUtilt::CellHoriJustify_CENTER # 文字横方向中央
oCell.VertJustify = CalcUtilt::CellVertJustify_CENTER # 文字縦方向中央
border = servmng.Bridge_GetStruct("com.sun.star.table.BorderLine2") # 枠線
border.Color = calcUtld.RGB(0, 0, 0)
border.LineWidth = 80 # 0.01mm ?
border.LineStyle = CalcUtilt::SOLID # 直線
oCell.BottomBorder = border # 枠線下端
id0 = calcUtld.getFormatCode(servmng, odoc, "#,##0") # セル数字表示形式
iy += 1
ssum = (ix + 1 + 'A'.ord).chr + (iy + 1).to_s
arfruits.each{|sf, ik|
oCell = sheet.getCellByposition(ix, iy)
oCell.String = sf
oCell.CellBackColor = calcUtld.RGB(0xaa, 0xff, 0xff) # バック色
oCell = sheet.getCellByposition(ix + 1, iy)
oCell.Value = ik
oCell.NumberFormat = id0 # セルの表示形式
iy += 1
}
ssum += ":" + (ix + 1 + 'A'.ord).chr + iy.to_s
oCell = sheet.getCellByposition(ix, iy)
oCell.String = "合計"
oCell.CellBackColor = calcUtld.RGB(0, 0x80, 0) # バック色
oCell.charColor = calcUtld.RGB(0xff, 0xff, 0xff) # 文字色
border.Color = calcUtld.RGB(0, 0, 0xff)
border.LineWidth = 80
border.LineStyle = CalcUtilt::SOLID
sheet.getCellRangeByPosition(ix, iy, ix + 1, iy).TopBorder = border # 枠線上端
oCell = sheet.getCellByposition(ix + 1, iy)
oCell.formula = "=sum(" + ssum + ")" # 合計関数 sum("C4:C7")
id0 = calcUtld.getFormatCode(servmng, odoc, "[$¥-411]#,##0;-[$¥-411]#,##0")
oCell.NumberFormat = id0 # セルの表示形式
isum = oCell.Value
print "合計=" + isum.to_s + "¥r¥n"
bprn = false
print "印刷しますか?(y/n)¥r¥n"
while true
sleep 0.01
ca = cons.inkey
if ca[0] == nil; next; end
if ca[0] == "y" || ca[0] == "Y"
bprn = true
end
break
end
if bprn == true # 印刷
oPrnOpt = Array.new(2, servmng.Bridge_GetStruct("com.sun.star.beans.PropertyValue"))
oPrnOpt[0].Name = "CopyCount" # 印刷部数
oPrnOpt[0].Value = 1
oPrnOpt[1].Name = "Pages" # 印刷ページ
oPrnOpt[1].Value = "1"
odoc.print(oPrnOpt)
end
print "qキーで終了¥r¥n"
while true
ca = cons.inkey
if ca[0] == "q" || ca[0] == "Q"
break
end
sleep 0.01
end
sfile = __dir__ + "/calcf例4.ods" # 保存ファイル名
print sfile + "¥r¥n"
if File.exist?(sfile) == true
File.delete(sfile)
end
sfname = "file:///" + sfile.gsub("¥¥","/")
odoc.storeAsURL(sfname, []) # 名前を付けて保存
odoc.close(true)
odoc = nil
desktop.terminate()
desktop = nil
servmng = nil
下記プログラム例における odoc, sheets, sheet 変数については上記プログラムを参照して下さい。
sheet = sheets.getByName("シート名") # シート名でシート選択
sheet = sheets.getByIndex(1) # インデックスNO.でシート選択 0~
p sheet.Name # シート名表示
sheet = odoc.getCurrentController().ActiveSheet # アクティブシートを選択
sheet2 = sheets.getByName("Sheet2")
odoc.getCurrentController().setActiveSheet(sheet2) # sheet2 をアクティブに
icu = odoc.sheets.getCount() # シート数取得
# 全シート名取得
arshnm = [] # シート名を入れる配列
oEnum = sheets.createEnumeration() # シートコレクション
while oEnum.hasMoreElements() do
arshnm >> oEnum.nextElement.Name
end
p arshnm
br = sheets.hasByName(sheetName) # シート名でsheetの存在確認 true:あり false:なし
# シート追加 第1引数:シート名 第2引数:シート挿入インデックス
sheets.insertNewByName("新シート", 0) # 0:先頭に追加
sheets.moveByName("Sheet1",0) # シートの移動 Sheet1をインデックス0(一番左)へ移動
sheets.removeByName("Sheet1") # シート削除 シート名を指定
oCell = sheet.getCellRangeByName("B2") # セルをRANGEで指定
oCell = sheet.getCellByposition(1, 2) # セル"B3"を指定 列,行で指定 0~の数字
oCell = sheet.getCellRangebyName("B7:D8") # セルをRANGEで指定
oCell = sheet.getCellRangeByPosition(1, 6, 3, 7) # RANGE"B7:D8"を列,行数字で指定 左上右下 0~
oCell.Value = 1.23 # 数値で代入
oCell.String = "日本" # 文字列で代入
oCell.Formula = "=SUM(B2:B3)" # 関数をセット
sheet.getCellRangeByName("B3").Value = 345
sheet.getCellByposition(1, 3).string = "セルBの4"
va = oCell.Value # セル値を数値で取得 ※1
vs = oCell.String # セル値を文字列で取得 文字コードは、「Windows-31J」 ※2 ※3
vf = oCell.Formula # セル値の関数を取得
# B3:C4の内容を配列で読み込む
sheet.getCellRangeByName("B3").Value = 345
sheet.getCellRangeByName("C3").string = "文字C3"
sheet.getCellRangeByName("B4").Value = 23.56
sheet.getCellRangeByName("C4").string = "文字C4"
arDt = sheet.getCellRangeByName("B3:C4").getDataArray() # 配列で読み込み
p arDt # [[345.0, "文字C3"], [23.56, "文字C4"]]
# B2:C4へ配列で書き込む
#arDt = WIN32OLE_VARIANT.array([2,3], WIN32OLE::VARIANT::VT_R4 | WIN32OLE::VARIANT::VT_BSTR) # VARIANT型配列
arDt = WIN32OLE_VARIANT.array([2,3], WIN32OLE::VARIANT::VT_VARIANT) # VARIANT型配列
arDt[0,0] = "項目1"; arDt[1,0] = 10.1
arDt[0,1] = "項目2"; arDt[1,1] = 11.2
arDt[0,2] = "項目3"; arDt[1,2] = 12.3
sheet.getCellRangeByName("B2:C4").setDataArray(arDt) # 配列で書き込み
# B2:C4 を B6:C8 へコピー
oRanges = sheet.getCellRangeByName("B2:C4").getRangeAddress()
oCelld = sheet.getCellRangeByName("B6").getCellAddress()
sheet.copyRange(oCelld, oRanges)
※1 データのないセルまたは、文字列のセルをValueで読んだ場合は、「0.0」となります。
※2 データのないセルをStringで読んだ場合は、""となります。また、数値セルを読んだ場合は、文字列として取得出来ます。
※3 セル内で改行がある場合は、改行コード¥n(LF)がセットされます。
# 名前を付けて保存 編集中ファイル名はそのまま
sfile = __dir__ + "/calcf例5.ods" # 保存ファイル名
sfname = "file:///" + sfile.gsub("¥¥","/")
odoc.storeAsURL(sfname, []) # 保存
# 上書き保存
odoc.store() # 既存のファイルを開いて上書き保存
odoc.print([])
# 印刷部数、印刷ページを指定
oPrnOpt = Array.new(2, servmng.Bridge_GetStruct("com.sun.star.beans.PropertyValue"))
oPrnOpt[0].Name = "CopyCount" # 印刷部数
oPrnOpt[0].Value = 1
oPrnOpt[1].Name = "Pages" # 印刷ページ
oPrnOpt[1].Value = "1"
odoc.print(oPrnOpt)
# 印刷処理終了まで待ちます
oPrnOpt = Array.new(1, servmng.Bridge_GetStruct("com.sun.star.beans.PropertyValue"))
oPrnOpt[0].Name = "Wait"
oPrnOpt[0].Value = true
odoc.print(oPrnOpt)
# 印刷プリンタを指定 印刷前に実行
oPrnterOpt = Array.new(1, servmng.Bridge_GetStruct("com.sun.star.beans.PropertyValue"))
oPrnterOpt[0].Name = "Name"
oPrnterOpt[0].Value = "Canon LBP*****" # "Microsoft Print to PDF"
odoc.setPrinter(oPrnterOpt)
・印刷するシートはアクティブにします。
・印刷プリンタを指定しない場合は、通常使うプリンタに出力されます。
・Wait を指定しない場合、印刷 print 実行後すぐにプログラムを終了すると印刷されません。
参考
OSS( Open Source Software )でいこう!!
OOoBasic/Calc