Search code examples
macroslibreoffice-calc

How to change a cell value periodically in libreoffice calc?


The title says it all...

For example, if I want to have a cell which displays the current time and auto updates minute by minute (well, I think we call that a clock), how do I do it?

Is there a simple function implemented already or should I create a macro and assign it to a specific event?

EDIT: Following the provided answer by @Jim K, I want to be more clear about what I want. The "clock" example above was here to make it simple to understand, but what I really want is in the title: a cell value which changes periodically, be it a string, a number, a date...


Solution

  • First enter =NOW() in a cell, and format the number by going to Format -> Cells.

    Next, this Basic macro (from here) recalculates every minute. Go to Tools -> Customize and assign it to the Open Document event.

    Sub RecalculatePeriodically
       Const secs = 60
       On Error Goto ErrorHandler
       Do While True
          Wait(1000 * secs)
          ThisComponent.calculateAll()
       Loop
       ErrorHandler:
           'Document was probably closed
    End Sub
    

    However, this crashes when exiting LibreOffice. So instead, use the following threaded Python macro (like here). Assign keep_recalculating_thread to the Open Document event.

    import time
    from threading import Thread
    import uno
    
    def keep_recalculating_thread(action_event=None):
        t = Thread(target = keep_recalculating)
        t.start()
    
    def keep_recalculating():
        oDoc = XSCRIPTCONTEXT.getDocument()
        while hasattr(oDoc, 'calculateAll'):
            oDoc.calculateAll()
            time.sleep(60)
    
    g_exportedScripts = keep_recalculating_thread,
    

    Another idea is at https://ask.libreoffice.org/en/question/5327/how-can-i-run-a-macro-at-regular-time-interval/, although it requires linking to another file which seems cumbersome.

    EDIT:

    Maybe you are looking for something like this? Test it by starting with a blank spreadsheet and entering 1 in cell A1.

    def keep_changing_cell(action_event=None):
        t = Thread(target = keep_changing_thread)
        t.start()
    
    def keep_changing_thread():
        oDoc = XSCRIPTCONTEXT.getDocument()
        oSheet = oDoc.CurrentController.ActiveSheet
        COLUMN_A = 0
        FIRST_ROW = 0
        oCell = oSheet.getCellByPosition(COLUMN_A, FIRST_ROW)
        while hasattr(oDoc, 'calculateAll'):
            oCell.setValue(oCell.getValue() + 1)
            time.sleep(2)