如何使用 Basic 而不是 Python 在 Calc 中选择宏中的单元格范围?

问题描述 投票:0回答:1

(上下文如下,有兴趣的朋友可以了解一下。)

我正在慢慢为 LibreOffice Calc 开发一组宏,从“记录宏”开始工作,然后尝试进行编辑,直到获得通用解决方案。我被选择方面困住了。

在许多示例或文档中我发现类似这样的内容:

selection = ThisComponent.CurrentSelection

现在我想创建这样的代码伪代码来完全自动化我的宏,但找不到Calc的正确语法:

selection = ThisComponent.RangeByName("D2:oLastActiveCell")
now, dear macro, do the actual selecting
now do some actual work to freshly defined selection

我读了很多书,发现了这个很有前途的“工具”:

getCellRangeByName()
我发现它不能开箱即用,我需要定义一些关于活动工作表的内容,例如
ThisComponent.Sheets(0)
似乎要“进行”实际选择,我可以使用类似
ThisComponent.CurrentController.Select(oHereTheAreaNeeded)
的东西 因此,当我将“工作”应用到我的选择时,我的宏会转到某个点,然后会收到大量错误消息。

当我通过鼠标拖动手动选择时,宏的“工作”部分运行良好(请参阅下面的上下文部分),因此显然我缺少元素,或者无法以正确的顺序将选择部分组合在一起。抱歉,如果这太明显了。我正在从头开始学习这个。还有其他方面,例如打开文件、删除列或排序,我已经弄清楚了。我并不是想偷懒。

请注意,我已经计算出了“oLastActiveCell”的值,所以这不是这个问题的一部分。你可以读一下 selection = ThisComponent.RangeByName("D2:D215")

如果对选择问题有帮助。

===

背景:我需要批量处理大量银行对账单(未来十年,来自几家不同银行),以准备将其导入会计程序。这些报表相当庞大且丑陋,但幸运的是它们每个月的结构都相同,因此我正在开发一个用户永远不需要打开 CSV 文件的工作流程。

这就是为什么“CurrentSelection”无法完成这项工作,因为没有人类用户,任何人都不会选择任何内容。但我确切地知道工作要在哪里完成。在这种情况下,从 D2 到 D215 又名 D2:D215 特定月份,一般为 D2:oLastActiveCell

对于那些想了解更多的人:对所选区域(范围?)做了什么,我在上面的伪代码中称之为“实际工作”?在我目前的阶段,我正在根据会计需要应用参考号。我正在 Calc 中使用“使用串联线性填充单元”功能。

宏知道(从对话框中)第一个参考号

oFirstReference

,并将计算出任何银行对账单中有多少个活动行。因此,应该对选择进行类似的操作

(当我手动选择范围时,这部分已经运行良好)
,因此仅作为上下文给出: dim args65(5) as new com.sun.star.beans.PropertyValue args65(0).Name = "FillDir" args65(0).Value = "B" args65(1).Name = "FillCmd" args65(1).Value = "L" args65(2).Name = "FillStep" args65(2).Value = "1" args65(3).Name = "FillDateCmd" args65(3).Value = "D" args65(4).Name = "FillStart" args65(4).Value = "oFirstReference" args65(5).Name = "FillMax" 'I do not understand this line, was added by record macro args65(5).Value = "1,7E+307" 'this is possibly a protection agains some overrun? dispatcher.executeDispatch(document, ".uno:FillSeries", "", 0, args65())

	
selection libreoffice-calc libreoffice-basic
1个回答
0
投票

Sub selectD2_LastUsedCell() Dim oCurrentController As Variant Dim oActiveSheet As Variant Dim oCellD2 As Variant Dim oCursor As Variant oCurrentController = ThisComponent.getCurrentController() oActiveSheet = oCurrentController.getActiveSheet() oCellD2 = oActiveSheet.getCellRangeByName("D2") oCursor = oActiveSheet.createCursorByRange(oCellD2) oCursor.gotoEndOfUsedArea(True) oCurrentController.select(oCursor) End Sub

现在我将尝试说服您,您不需要这个子例程来解决您的问题。
在 Calc 和 Excel 中,视觉操作大大减慢了脚本的执行速度。因此,强烈建议从代码中删除与选择工作表单元格范围相关的所有操作,它们在处理数据时没有任何帮助,它们是有害的。
事实上,您的任务是获取并处理电子表格中的数据。而且这样做的方式有所不同。

Sub processAllSheets() Dim oDoc As Variant Dim oSheets As Variant, oSheet As Variant, oCursor As Variant Dim nEndColumn As Long, nEndRow As Long, nRow As Long Dim oRange As Variant Dim aDataArray As Variant, aRow As Variant oDoc = ThisComponent oSheets = oDoc.getSheets() For Each oSheet In oSheets oCursor = oSheet.createCursor() oCursor.gotoEndOfUsedArea(False) nEndColumn = oCursor.getRangeAddress().EndColumn If nEndColumn > 2 Then ' If the last filled column is less than D, there is no point in continuing nEndRow = oCursor.getRangeAddress().EndRow If nEndRow > 1 Then ' If there are no values ​​below cell D2, then there is no point in continuing. oRange = oSheet.getCellRangeByPosition(3, 1, nEndColumn, nEndRow) aDataArray = oRange.getDataArray() For nRow = LBound(aDataArray) To UBound(aDataArray) aRow = aDataArray(nRow) ' Here do something with the data of each row of your table ' Just for example - show content of this row Print Join(aRow,"; ") Next nRow EndIf EndIf Next oSheet End Sub

如果您能够阅读并理解此过程的代码,您将能够快速完成您的项目。否则,您应该下载

Andrew Pitonyak的英文宏观文档。您不需要立即阅读所有内容,将列表用作菜谱中的菜谱 - 很快您就会了解 LibreOffice 编程的本质(并且会惊讶于您最初解决问题的方法是多么错误)。

© www.soinside.com 2019 - 2024. All rights reserved.