Macro to select and move cells, and copy one cell formula

I need a Calc macro which will move all cells in four contiguous columns – except those in the first two rows – down one row, and then copy/extend the formula from a cell in what is now the 4th row up to the now empty cell directly above it.

I know: That’s a confusing explanation. Clearer details, images, and attached example spreadsheets follow. But my basic problem is that while I can perform the required actions using the mouse, I can’t figure out how to do it using only the keyboard, and if I understand correctly this means I can’t use the macro recorder to create such a macro. While I have extensive programming experience, the learning curve for the macro APIs is very steep, and I’m hoping some knowledgeable and kind person can help me with what is probably a simple task for them.

I keep my personal finances in a very simple, very ordinary Calc spreadsheet, for example:


oldest_at_top.ods (26.9 KB)

I always keep a horizontally split view with the first two header rows visible, including a very clever formula that someone here provided to me (sorry, forgot who and when, but thanks again to whoever it was) for example in the D1 cell: =OFFSET(D3,COUNT(D3:D1000)-1,0,1,1) which finds the most recent balance in column D and displays it in the header area.

The spreadsheet has worked well for many years, but the above formula only partly solves what’s become an increasingly annoying usage problem. In contrast to this simple example, the real spreadsheet has many more accounts spanning additional columns, and the accounts have widely differing numbers of rows in them. Some have a few dozen while others have many hundreds. The split view and the clever formula means I can scroll horizontally to check all the accounts’ current balances. But to add new entries to an account I have to manually scroll up and down to find the first (lowest) blank row, and then repeat the process for other accounts. Note that I do not want to keep each account on a separate sheet (which I could keep scrolled to the bottom) – being able to quickly scroll horizontally to check the all balances is an important feature.

As time has gone on and the spreadsheet has grown and become increasingly difficult to use, it’s occurred to me that what I really need is to reverse to order of the columns so that newest entries are at the top:


newest_at_top.ods (26.4 KB)

This eliminates the need for the split view and clever formula because the current balances are always visible at the top (in row 3). It’s also additionally better because having the more recent history visible is more useful.

But it presents a different problem, the need for a macro as described at the start of this overly long post. To add a new entry I have to select columns F through I (for example), then do Edit -> Select -> Select Data Area (or use CTRL+*), then use CTRL+mouse to de-select F1 through I2, then mouse-drag the entries down one row, and then click on I4 to drag its formula up to I3 before finally being able to enter a new transaction in F3 through H3. (If it weren’t for Select Data Area I’d have to manually select from F3 through I3 down to the oldest entries, which would be right back to the current problem in oldest_at_top.ods.)

Again, I’d be grateful for any help creating a macro to do this, either a way to do all the actions without using the mouse if that would allow Record Macro to work, or explicit macro code otherwise. Bonus points if the code is in Python which I’m fairly experienced with – I haven’t programmed in Basic for more decades than I care to admit, but that would be OK too (either to use blindly as-is or as a starting point for tweaking/hacking).

Regardless, thanks to anyone who’s read this far even if you can’t provide any help with my requests.

If purposes of the kind are handled using spreadsheets, it’s a good idea to add new datasets at top of the data range.
A separation should then better be made using the Freeze feature instead of using the splitter.
However, the concept isn’t very well supported (automized), and gives rise to further considerations including the need of user code.
See attached example:
newDataAtTop.ods (34.8 KB)
It may help a bit with learning about the API (and Basic).

Thanks, @Lupp. I’m currently reviewing the spreadsheet and macro you generously provided. It looks like a good starting point for conversion to what I need.

You’re inserting an entire row whereas I need to insert cells in range of columns, but Macros/Basic/Calc/Ranges - The Document Foundation Wiki seems to have some good information on how to do that. What worries me most is that I read somewhere in the documentation or forums that it’s difficult (or impossible?) to access the column+row address of the currently selected cell. My macro requires something like that because it needs to know which columns should have their cells moved. As I wrote, I have many accounts, each with their associated columns, and it would be impractical to have multiple/separate/individual macros for each.

I agree that it’s better to add new entries at the top – that’s what led me to create this post. I didn’t know about the “Freeze” feature – thanks for educating me about it. As you point out it’s much better than “Split Window” for this use-case. (I’d sometimes mistakenly scroll the top/“header” split window and have to reset it, which can’t happen with “Freeze”.)

Regarding (re-)learning Basic, it’s changed a lot since the days when I last used it (search for “Dartmouth BASIC” if you’re interested in ancient history). Still, the general consensus is that there are better alternatives, possibly even to the point of the early computer science pioneer Edsger Dijkstra’s famous quote: “It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration.” :wink:

Even Microsoft moved on to other things like C# (keep in mind that Bill Gates founded the company with his Basic interpreter, long before DOS much less Windows). It’s very impressive that LibreOffice offers Python among other alternatives. But if Basic is the default, best supported language, that’s fine. As I wrote before, the issue for me is the learning curve for the APIs regardless what language is used to access them, so I’ll be modifying your code in Basic at least for now.

Thanks again, and I’ll try to solve this on my own without coming back here with too many more questions.

In case anyone else is interested in this, I think I’ve found a solution, and it was much easier than I thought it would be.

Regarding something I asked in my original post, it is possible to perform the desired actions using only the keyboard (no mouse), and thus possible to capture the commands using RECORD_MACRO. I didn’t know that SHIFT+<arrow key> extends a range of selected cells, that CTRL+<arrow key> jumps to the last cell that contains data, and that the two can be combined as SHIFT+CTRL+<arrow key>.

These were the missing functionalities I needed. Starting with selecting cell F3 (for example) in newest_at_top.ods:

  1. 4x SHIFT+RIGHT (select cells F3 thru I3)
  2. CTRL+SHIFT+DOWN (extend selection to last row with data)
  3. CTRL+X (cut selection)
  4. CTRL+UP (jump up to cell F1)
  5. 3x DOWN (to cell F4)
  6. CTRL+V (paste selection)
  7. 3x RIGHT (to cell I4)
  8. CTRL+C (copy formula in cell I4)
  9. UP (to cell I3)
  10. CTRL+V (paste formula)
  11. 3x LEFT (to cell F3)

This produces the BASIC macro in
OpenNewEntryMacro.zip (880 Bytes)

(contains file OpenNewEntryMacro.txt – had to ZIP to allow upload.)

I used Tools -> Customize to assign the macro to an unused key, and it does (almost) exactly what I want – in particular working on any set of columns with account transactions. The only remaining problem is that the new date cell loses its format. I tried adding:

Dim selection As Object
selection = ThisComponent.CurrentSelection
selection.NumberFormat = “YYYY-MM-DD”

to the bottom of the macro (before end sub) but it didn’t do anything. I’ve had this problem before, that newly blank cells (after moving their contents elsewhere) lose their formatting. If I can’t find a way to do it in the macro, maybe setting the date format in Default style will work.

Thanks again to @Lupp for encouraging me to look into LibreOffice BASIC programming.

That’s a misunderstanding:

  • Recorded macros are neither actual Basic nor “Programming”.
    They are next to no use concerning learning how to get things done.
  • They are extremely specialised, and an adaption after any little change in the strucure of a sheet (e.g.) mostly requires a full new recording.
  • My attempt concerned an initiation into using the LibO API based on an example.
  • Mixing recorded macros with written Basic commands is possible but generally not recommended.
  • If you try it nonetheless you will again need to study the basics (and case-dependent details) of the LibO API - and of written LibO Basic.
  • Thus: Record your macro again and include the formatting in interactive mode with it. Use Copy / Paste Special... pasting Format only. Be aware that LibO may remember the “Format only” setting and later apply it when somebody is manually working on the sheet.again and expects something else.

selection.NumberFormat gives/takes not a format string but a key into the NumberFormats object
See attached example:
numberFormatKeyDemo.ods (12.6 KB)

Understood.

Understood about “learning”, but in this case I claim they were the best solution for someone like me who just wants to “get things done”.

OK, but the irony is that all of the BASIC API examples, tutorials, and documentation I found – with the exception of your super-expert-level focusCell function (which BTW I did find an earlier version of in your May I get the coordinates of the current cell as a variable? - #21 by karolus postings, and earlier) – deal with fixed/constant/absolute cell addresses and thus weren’t applicable to my needs.

(I also tried the techniques in Get the Selection Cell and Range Address using Macro in LibreOffice without success. But that page is 10 years old and maybe the APIs have changed since then.)

Again, thanks for your well-intentioned attempts to educate me, but in this case (and I think others who might have similar ones) the simpler the solution, the better.

That’s unfortunate, IMO. Most of the applications I’m familiar with that have macros and/or embedded language capabilities fully implement their UI as calls to the embedded APIs. If a captured macro can be viewed in its embedded language format (which unfortunately some apps don’t support) it becomes an excellent, low-learning-curve way for users to create a macro and lightly modify it as needed.

I tried, and fell into the black hole of the difficulty in accessing the currently active cell I mentioned I was afraid of in my previous post.

BTW, I am extremely familiar with case-sensitivity in computer language parsers. If a case typo was the only mistake I made that prevented my attempts from working I apologize for missing it.

OK, moving forward … I did record a new macro and it seems to work perfectly. If it breaks later due to a change in its spreadsheet I’ll have to deal with it then.

newest_at_top_with_macro.ods (28.3 KB)

Instead of using Paste Special..., etc. I merely copied the previous entry’s cells and “normal” pasted them. I then deleted the contents of one (the “amount” cell) but left the date as copied – it could be useful if adding multiple transactions on the same date, and if not, typing a new date (including Calc’s excellent CTRL+; shortcut for the current date) immediately overwrites the unwanted default one.

Because I already had this working before reading your reply, I didn’t experiment with Paste Special. I had thought about it, but don’t know how to access it without using the mouse, either through the main Edit menu or from the right-click context menu in the cell. And I thought the whole problem here was that mouse actions can not be captured with RECORD MACRO.

BTW, I’m also very familiar with the problem of macros that use global resources that the user doesn’t expect to be overwritten. Things like cut/paste buffers. I’m well aware that I’m doing that here but accept the tradeoff for simplicity’s sake.

My bad. I’d searched for how to do this and Google’s A.I. led me astray:

Example 2: Set Date Format
i = 3: j = 2
oCell = oSheet.getCellByPosition(i, j)
oCell.NumberFormat = “D. MMMM YYYY” 'Format as Date, including day of the week

Never trust A.I., it’s plotting to take over the world and kill all humans. :wink:

I integrated your assignNumnerFormat() code into a version of my macro and of course it worked, but among other things I still need to set cell alignment and other formatting back to the way it was. (I still wish cells would retain their format after their contents have been cut/moved away.) (And I’m not sure setting the default style would help me because the “date” cells need date number format and the “amount” ones currency.)

In any case, once again the recorded macro seems to be the best solution for my use-case. I thank you for all the time and effort you’ve put into your responses here.

One last attempt at humor: If you’re not familiar with the English expression “pearls before swine”, look it up and see if you think it’s applicable here. :wink:

Why do you think it’s otherwise?

  • Use cell styles!
  • An explicitly assigned hard format attribute overrides the respective attribute defined for the style.
  • Concerning number formats there are cases of automatic formatting depending on the input or formula result type just for inconvenience :upside_down_face:. This should never override an explicitly set format (or CF).

Well, even an old teacher must stop teaching at some point.
One more remark: There is a slightly outdated phrase in German: “Das ist wie Perlen vor die Säue werfen.” You see, the languages still expose their common history “west of Sanskrit”.
Of course the phrase isn’t applicable in this case.

Perhaps this will help?



You may also find some other useful keyboard shortcuts in Shortcut Keys for LibreOffice Writer.

Yes, thanks. I should have checked and found that.

It works when using the ENTER key in the dialog that pops up with the default of only Paste:Formats checked, so should work with RECORD MACRO although I haven’t tested it yet. The only problem is that if I set other options in the dialog, the macro will apply those instead of what was intended/recorded. And although there are the explicit menu options for “Paste Only Text”, “Paste Only Numbers”, etc. which can be assigned to shortcuts, there’s no “Paste Only Formats” that I can find. That would be ideal for my use-case.

I may be misunderstanding you, but if I CTRL+X a cell that has had its format set, and then typically CTRL+V it into a different cell (although that isn’t necessary in this example), and then enter new data into the original cell, it will have default formatting, not the explicit formatting that was there before.

This has moved to the point where I’m just asking basic usage questions, so you should probably let me go back and read/watch some more beginner tutorials, but …

I’ve gone into Styles -> Manage Styles(F11), done Edit Style ... on “Default”, set Numbers -> Date to “YYYY-MM-DD”, and left Styles -> Default checked active, but dates entered into cells that don’t have explicit formatting still show up in “MM/DD/YY” format.

Again, I’ll try to figure out what I’m doing wrong, but I can commit user errors and/or break any software. :open_mouth:

That relates to my confusion about being able to set explicit/separate/non-conflicting Currency and Date formats simultaneously within a single cell, but I personally like the feature that entering either “.1” or “3/5” turns respectively into “$0.10” and “03/05/25”. Very smart context-sensitive programming. I just wish I knew how to control the specific formats.

Yes, if Google Translate can be trusted, that’s the same as the English version. Thanks again for your patience being the pearl-casting teacher while I’m the swine who ignores them and does things his own clumsy way. :wink:

Yes, this removes formatting (even an assigned cell style), but it’s simple to use Ctrl+C and Del instead, Del does not remove formatting.

You obviously use a en-US locale which is the one having set this idiotic format as default. Use en-CA (Canada) instead. Its date format defaults to ISO 8601 which you rightfuilly prefer.

This is confusing me now to some degree.
Concerning the dates you can define your preferred Date acceptance pattern. The recognized date (even if entered as M/D e.g. what seems to be your preferred shorthand pattern) will then be shown in the preset date format in the cell.
Concerning currency there are no acceptance patterns.
My advice: Dont use currency formatting at all! Use a column header like “Amount/USD” and enter ordinary numbers below.
With curreny-formatted cells you could easily prove that “1.00$ = 1¥”. Would you like your income to be “converted” this way?
I hope you will appreciate pearls in the future.
But I would also like to cease this “dialog” for a while.