最近剛好有數據分析的需求
想在Calc上寫個程式來加快我的數據分析的前置工作
(弄些自動改格式、儲存格上色、儲存格取值作判斷等的小動作)
因為要重複做同樣的事
所以想說寫個巨集來把上述的動作自動化
不過我只寫過C,沒碰過VB這類的語言
想說網路上是不是有新手教程可以看
結果一搜發現:資料還真是少!?
只看到這篇
其他中文網頁有可以直接套用的文章就很少了
對岸的CSDN上是有一些教程,不過下載還要點數,有點麻煩
所以我就開始自己搞了~
我一開始是直接用CALC的巨集直接錄下我在CALC上的動作
然後去看程式碼,把程式碼拆解成可用的小方塊來使用
這樣我就可以在不花太多時間去研究Basic的語法的情況下
實作出我想要的功能
不過目前LibreOffice(7.2.2版)的錄製巨集功能好像還很陽春
好像在CALC上只能錄製對儲存格的操作
所以這招還是有些限制的
後來我又研究了一段時間,找英文的資料
發現其實官網是有快速上手的指令參考的
官網的參考文件頁面是這個
用上面那個文件,基本上就可以很快地拼出你想要的基礎功能
====
下面寫寫我在網路上看了幾篇文章的小結論,可以參考參考:
在網路上搜尋『Porting Excel/VBA to Calc/StarBasic』(2004) 連結
裡面有寫到:LibreOffice Basic的語法跟VB應該是完全相通的
差別在於Calc 跟 Excel的架構:Calc是完全的物件導向,Excel則不是
Excel少了繼承這個部分
我又看到另一篇文章『OOP In VBA?』
在講Excel不是完全的物件導向設計,會有什麼問題
作者的結論是:其實也不一定完全是缺點
反正好用就好了,呵呵
像CALC是完全的物件導向,可是code就是超級長一串
對新手(像我就是)來說其實也不是很友善
總之,如果你就是剛好需要使用CALC(譬如不想用盜版MS Office or 其他)
那就只好接受CALC的設計,想辦法去讓code動起來
以下分享一些前面講的用巨集弄出來的code
給大家參考參考,基本上組一組就可以用了
底色是灰色的是code,說明加在code後面
至於官網的參考文件,我研究研究有什麼心得再PO上來吧~
======
1. 常用code功能區塊
<<宣告物件>>
dim document as object
dim dispatcher as object
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
說明:給完全沒碰過VB的人的解釋一下基礎語法
dim = dimensions,是Basic語言中的宣告的意思(這有些典故,欲知詳情請查英文資料)
rem => 註解 ,另外『`』也是註解
document , dispatcher 都宣告成物件,當作Handle
這兩個物件在後面每個模塊要設定的時候都會用到
基本上複製貼上就好了
dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "ToPoint"
args1(0).Value = "$A$1:$N$36"
dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args1())
dim args5(0) as new com.sun.star.beans.PropertyValue
args5(0).Name = "Color"
args5(0).Value = 0
dispatcher.executeDispatch(document, ".uno:Color", "", 0, args5())
說明:
0=黑色
<<修改字型為粗體>>
dim args2(0) as new com.sun.star.beans.PropertyValue
args2(0).Name = "Bold"
args2(0).Value = true
dispatcher.executeDispatch(document, ".uno:Bold", "", 0, args2())
<<修改字型大小>>
dim args4(2) as new com.sun.star.beans.PropertyValue
args4(0).Name = "FontHeight.Height"
args4(0).Value = 12
args4(1).Name = "FontHeight.Prop"
args4(1).Value = 100
args4(2).Name = "FontHeight.Diff"
args4(2).Value = 0
dispatcher.executeDispatch(document, ".uno:FontHeight", "", 0, args4())
說明:上面是錄製巨集自動產生的code
有沒有能刪掉的,我也不確定
可以自己實驗看看
懶的實驗就整個貼上去用
<<設定一個範圍的顏色 >>
REM ***** BASIC *****
Sub Main
dim document as object
dim dispatcher as object
dim szRange
rem ----------------------------------------------------------------------
rem get access to the document
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
szRange=MakeRangeString("R", 10, "R", 25)
msgbox (szRange)
SelectRange_ChangeColor(document, dispatcher, szRange)
End Sub
sub SelectRange_ChangeColor(document as object, dispatcher as object, szRange as string)
dim args2(0) as new com.sun.star.beans.PropertyValue
args2(0).Name = "ToPoint"
' args2(0).Value = "$O$10:$O$25"
args2(0).Value = szRange
dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args2())
rem ----------------------------------------------------------------------
dim args3(0) as new com.sun.star.beans.PropertyValue
args3(0).Name = "BackgroundColor"
args3(0).Value = 16776960
dispatcher.executeDispatch(document, ".uno:BackgroundColor", "", 0, args3())
end sub
function MakeRangeString(szStartCol as String, _
dStartRow as Integer, _
szEndCol as String, _
dEndRow as Integer) as String
MakeRangeString="$" & szStartCol & "$" & CStr(dStartRow) & ":$" & szEndCol & "$" & CStr(dEndRow)
end function
給Basic語言新手的說明:
Basic有兩種函式宣告
Sub是沒有回傳值的
Function是有回傳值的,回傳值是用函數名稱傳出去
rem後面是註解,只是排版用的,不要理他
另外,CALC中字串拼接可以使用"&"
另外document 跟 dispatcher 其實可以宣告成全域變數,拉到Main外面去就好了
function宣告後面那個『_』是換行的符號
這樣就可以不用寫一長串擠在一行裡,很不好看
<<改特定行的顏色 & 設置Filter>>
REM ***** BASIC *****
rem ==== color table ====
const clrYELLOW_DARK = &hF9F900
const clrYELLOW = &hFFFF00
const clrYELLOW_LIGHTER = &hFFFFAA
const clrYELLOW_LIGHT = &hFFFFDF
const clrGOLD_DARK = &hEAC100
const clrGOLD = &hFFDC35
const clrGOLD_LIGHTER = &hFFED97
const clrGOLD_LIGHT = &hFFF8D7
const clrORANGE = &hFFA042
const clrORANGE_LIGHTER = &hFFBB77
const clrORANGE_LIGHT = &hFFDCB9
const clrGREEN_DARK = &h73BF00
const clrGREEN = &h8CEA00
const clrGREEN_LIGHTER = &hA8FF24
const clrGREEN_LIGHT = &hD3FF93
rem =====================
Sub Main
dim document as object
dim dispatcher as object
dim szRange
rem ----------------------------------------------------------------------
rem get access to the document
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
rem === set color for interested item ===
szRange=MakeRangeString("C", 2, "C", 1000)
SelectRange_ChangeColor(document, dispatcher, szRange, clrGREEN_DARK)
szRange=MakeRangeString("E", 2, "E", 1000)
SelectRange_ChangeColor(document, dispatcher, szRange, clrGREEN_DARK)
szRange=MakeRangeString("G", 2, "G", 1000)
SelectRange_ChangeColor(document, dispatcher, szRange, clrGREEN_DARK)
rem === set color for parameters ====
szRange=MakeRangeString("K", 2, "K", 1000)
SelectRange_ChangeColor(document, dispatcher, szRange, clrGOLD_LIGHT)
szRange=MakeRangeString("L", 2, "L", 1000)
SelectRange_ChangeColor(document, dispatcher, szRange, clrGOLD_LIGHT)
szRange=MakeRangeString("M", 2, "M", 1000)
SelectRange_ChangeColor(document, dispatcher, szRange, clrGOLD_LIGHT)
SetFilter(document, dispatcher)
End Sub
Sub SelectRange_ChangeColor(document as object, dispatcher as object, _
szRange as string, dColor as long)
dim args(0) as new com.sun.star.beans.PropertyValue
args(0).Name = "ToPoint"
args(0).Value = szRange
dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args())
rem ----------------------------------------------------------------------
args(0).Name = "BackgroundColor"
args(0).Value = dColor
dispatcher.executeDispatch(document, ".uno:BackgroundColor", "", 0, args())
End sub
Function MakeRangeString(szStartCol as String, _
dStartRow as Integer, _
szEndCol as String, _
dEndRow as Integer) _
as String
MakeRangeString="$" & szStartCol & "$" & CStr(dStartRow) & ":$" & szEndCol & "$" & CStr(dEndRow)
End Function
Rem: Go to A1 and set filter
Sub SetFilter(document as object, dispatcher as object)
dim args(0) as new com.sun.star.beans.PropertyValue
args(0).Name = "ToPoint"
args(0).Value = "$A$1"
dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args())
rem ----------------------------------------------------------------------
dispatcher.executeDispatch(document, ".uno:DataFilterAutoFilter", "", 0, Array())
End Sub
=====
後面有什麼心得再來補上吧~
謝謝觀賞~
留言列表