This kind of recorded macro is a wondeful example for perfection: Perfect uselessness.
How do I repeat the action in the following Cell A133?
Without going to the spreadsheet, click the next cell and run the macro again?
Did you read the recorded code? If so you will have noticed that the cell address is recorded as a text
constant. Therefore: If you go anywhere in the same sheet and run the "macro" it will always act on the inevitably same cell.
If you want to repeat a (most likely modified in steps) action for a range of adjacent cells you have to do as Zizi64 told you.
1. Forget about recording macros. (In rare cases for completely different tasks there may sometimes be some sense in macro recording.)
2. Learn how to get a cell range.
2.a Get the spreadsheet document.
2.b Get the single sheet you need to work in.
2.c Get the cell range as a part of the sheet.
3. Loop through the cells of the range and perform the respective actions.
The "active cell" seems to be an important player in MS Excel VBA code. It is not in Calc. In fact it is next to impossible to get the "active" cell if the term is meant to mean the cell currently having the input focus. Calc knows the active sheet and the current selection. Again: The Api does not "know" (give access to) the cell under focus, and this cell is not necessarily part of the current selection.
Let's assume you just clicked on a single cell's area. In this special case the current selection is a cell range consisting of a single cell. You can now run the following BASIC code using the api (not the dispatch helper):
Code: Select all
Sub FillABC3wide5high()
myDoc = ThisComponent
mySel = myDoc.CurrentSelection
mySheet = mySel.Spreadsheet
REM Now wanting to work on a range starting with the selected cell
REM or with the topmost leftmost cell of the selected range.
REM Suppose 3 columns wide and five rows high the cells shall get the text content "ABC".
myRange = mySheet.GetCellRangeByPosition(mySel.RangeAddress.StartColumn, _
mySel.RangeAddress.StartRow, _
mySel.RangeAddress.StartColumn + 3-1, _
mySel.RangeAddress.StartRow + 5-1)
For m = 0 To 5-1
For n = 0 To 3-1
oneCell = myRange.GetCellByPosition(n, m)
oneCell.String = "ABC"
Next n
Next m
REM The selection is still unchanged, and we didn't need to access an "active cell.
REM In fact we could do this very well without creating the myRange object.
End Sub
I tested this for 1000 columns instead of three and 5000 rows instead of 5. I had to interrupt the Sub because a thorough estimate told me it would run about 1 h 10 min.
Looping through cells creating each one as an object is slow!
Is there remedy?
I made a similar Sub creating a copy of the DataArray of the complete range, filling it as needed, and writing it back to the range in one go:
Code: Select all
Sub FillWithText() ' For actual use: (ByVal pText As String, ByVal pWidth As Long, ByVal pHeight As Long)
REM Only for the test:
pText = "ABC?" : pWidth = 1000 : pHeight = 5000
myDoc = ThisComponent
mySel = myDoc.CurrentSelection
mySheet = mySel.Spreadsheet
myRange = mySheet.GetCellRangeByPosition(mySel.RangeAddress.StartColumn, _
mySel.RangeAddress.StartRow, _
mySel.RangeAddress.StartColumn + pWidth-1, _
mySel.RangeAddress.StartRow + pHeight-1)
myDataArray = myRange.GetDataArray
For m = 0 To pHeight-1
For n = 0 To pWidth-1
myDataArray(m)(n) = pText
Next n
Next m
myRange.SetDataArray(myDataArray)
End Sub
I didn't need to interrupt this Sub. It completed the task in 49 s. Speed factor about 86. OK, it used an additional amount of RAM, of course.
It pays to consider efficiency.