libreoffice-basiclibreoffice-base

How would I set focus in a LibreOffice macro (for use in a Base form)? Or set up a "Position-To" field that DOESN'T filter?


In a LibreOffice Base form, I have a button set to call .uno:RecSearch, in order to bring up the record search dialog.

The problem with that is that if no field in the form has focus, the record search dialog comes up with the third of seven date fields in the form as the search target (which is pretty much useless), rather than the desired "Name" field. (And even more puzzling, the listbox to select which field to search seems to have the fields in more-or-less random order).

I would like to create a macro for a LibreOffice Base form, that would first set focus to the "Name" field, then call .uno:RecSearch.

Can that be done, and if so, how?


Solution

  • I never did find a way to do that (although I found that the sequence of fields as seen by macros bears no resemblance to the nominal sequence of the fields in the record or on the screen, which is a puzzle in itself), but I found something that, for my purposes, is better: how to implement a "Position To" field (as contrasted with a filter, which is precisely what I don't want!) with a macro, attached to the "Changed" event of a "Position To" field added to the form.

    option explicit
    
    sub PositionTo (e as object)
    dim c as object
    dim oDoc, oDrawpage, oForm, oName, oConnection as object
    
    oDoc = thisComponent
    oDrawpage = oDoc.drawpage
    oForm = oDrawPage.forms.getByName("MainForm")
    oName = oForm.getByName("txtName")
    
    
       if ucase(e.source.text) < ucase(oName.text) then
         do until (ucase(e.source.text) > ucase(oName.text)) or (oForm.isBeforeFirst)
           oForm.previous
         loop
         oForm.next
    
       else
         do until (ucase(e.source.text) <= ucase(oName.text)) or (oForm.isAfterLast)
           oForm.next
         loop
         if oForm.isAfterLast then oform.previous
       endif
    end sub
    

    It is, of course, a brute-force approach, that would have serious performance problems in a database with more than a few thousand records, but then again, a database with more than a few thousand records would call for something more sophisticated than LibreOffice Base over its own built-in (and rather out-of-date) HSQLDB.

    The situation is a table, in which the unique primary key is a non-case-sensitive text field.

    First, we define our variables, and get hold of the form and the keyfield's presence on the form. Then, we check whether the value of the "Position To" field ("e.source.text") comes before the current record's key value ("oName.text"), ignoring case.

    If we're after the Position To value, then we step backwards through the records until we get to a record before our "Position To" value, or we're at the top of the file, then step forward one record.

    If we're before the Position To value, then we step forward until we reach the first record that's at least a match, or we hit EOF; if the latter, we back up to the last record.

    Performance could of course be improved for long sweeps by doing it in two stages, with longer steps for the first stage, but that would be more trouble than it's worth, given the size of the database.

    But of course, I would welcome any viable, practical, suggestions for improvements. And if there's an existing "position to" function I don't know about, that would help.