Cases in Libreoffice

How to implement cases in LibreOffice?

I have a surname, let’s say Ivanov, Semenov. How can I automate changing the name to Ivanova, Semenova? That is, to the accusative case?

Yes, this must be done in the Ukrainian language.

I tried using pymorphy2, installed the necessary libraries in python, copied the pymorphy2 and pymorphy2_dicts_uk folders to /usr/lib/libreoffice/share/Scripts/python and created a script

import pymorphy2

# Ініціалізуємо морфологічний аналізатор
morph = pymorphy2.MorphAnalyzer(lang='uk')

def change_case(word, case):
    # Розбираємо слово
    parsed = morph.parse(word)[0]
    # Перевіряємо, чи можна відмінювати у вказаному відмінку
    if case in parsed.tag.cases:
        inflected = parsed.inflect({case})
        if inflected:
            return inflected.word
    return word

but I did not find how to execute the script.

I also tried the following code through basic

Function ChangeCase(word As String, caseType As String) As String
    Dim scriptProvider As Object
    Dim pythonScript As Object

    ' Отримання доступу до Python-скриптів
    scriptProvider = ThisComponent.getScriptProvider()
    pythonScript = scriptProvider.getScript("vnd.sun.star.script:morphology.change_case?language=Python&location=user")

    ' Виклик Python-функції з параметрами
    Dim args(1) As Variant
    args(0) = word
    args(1) = caseType
    ChangeCase = pythonScript.invoke(args)
End Function

It gave an error…

Wich error? (Text of the message)

Do you run this function directly from Basic IDE? Yes, in this case you will get an error

Try create new spreadsheet and put to any cell formula like as
=CHANGECASE("Ілля";"man")
(or which second param must be)

IMHO, the error in the second screenshot is related to an incomplete line - the script location is missing &location=…

pymorphy2 Would need to be installed on the python path.

The news version of APSO has an experimental pip installer, which I have not tried yet.
I am the author of LibrePythonista which may be a overkill for your needs at this time. It is for Calc but it also has a pip installer and the install package are available for all of LibreOffice.

I recommend installing APSO and open the console if you want to see LibreOffice current python paths.

>>> import sys
>>> import pprint
>>> pprint.pprint(sys.path)
['/usr/lib/libreoffice/program',
 '/usr/lib/python312.zip',
 '/usr/lib/python3.12',
 '/usr/lib/python3.12/lib-dynload',
 '/home/paul/.local/lib/python3.12/site-packages',
 '/usr/local/lib/python3.12/dist-packages',
 '/usr/lib/python3/dist-packages',
 '/usr/lib/libreoffice/program',
 '/home/paul/.config/libreoffice/4/user/uno_packages/cache/uno_packages/lu9698823wtas0.tmp_/apso.oxt/python/pythonpath']

This is just the start of getting python to work in this case.
The /usr/lib/libreoffice/share/Scripts/python will not be on the python path and must be called as a macro.
With a proper setup you can import pymorphy2 in the macro code and run it.

For python you have a bit of a complex use case.
There are custom ways to accomplish this but require more advance python skills.
And finally you could create a custom extension for LibreOffice, probably huge overkill but just in case you would want to do such a thing.
I would recommend using my Python LibreOffice Pip Extension Template as a starting point. It is complex; however, it can create a simple python extension in a matter of minutes.
Even LibrePythonista is built from this template.

No, I run this function through a formula in a table cell.

I use almost the same formula, one difference is that instead of the word “Ілля” I indicate the number of the cell from where to take the data.

Можливо ви розумієте українську, чи російську мови?

It seems that’s exactly what I tried to do, but something went wrong.
Maybe you can help with the proper call and setup?

I’m not at all against participating in the creation of such an extension, but my current knowledge of Python does not allow me to do it properly.
That’s why I created this topic.

In general, I personally think that such an extension would be very useful.
Because I’m not the only one who needs automatic case declension.
However, my knowledge of Python and Macro does not allow me to create such an extension myself.

Therefore, I suggest everyone to join this topic :slight_smile:

I almost got this working in LibrePytonista.
Can you post your full python code please.

I think also that pymorphy2 is outdated.
I am running currently on Ubuntu 24.04 With LibreOffice 24.8.
Which is using python 3.12

Here is the code I am trying:

import pymorphy2
try:
    morph = pymorphy2.MorphAnalyzer(lang='uk')
except Exception:
    lp_log.exception("error setting morph")

def change_case(word, case):
    # Розбираємо слово
    parsed = morph.parse(word)[0]
    # Перевіряємо, чи можна відмінювати у вказаному відмінку
    if case in parsed.tag.cases:
        inflected = parsed.inflect({case})
        if inflected:
            return inflected.word
    return word

I am getting errors from pymorphy2.

2024-11-04 13:30:07,123 - ERROR - PyLogger: error setting morph
Traceback (most recent call last):
  File "<string>", line 3, in <module>
  File "/home/paul/.local/lib/python3.12/site-packages/pymorphy2/analyzer.py", line 224, in __init__
    self._init_units(units)
  File "/home/paul/.local/lib/python3.12/site-packages/pymorphy2/analyzer.py", line 235, in _init_units
    self._units.append((self._bound_unit(unit), False))
                        ^^^^^^^^^^^^^^^^^^^^^^
  File "/home/paul/.local/lib/python3.12/site-packages/pymorphy2/analyzer.py", line 246, in _bound_unit
    unit = unit.clone()
           ^^^^^^^^^^^^
  File "/home/paul/.local/lib/python3.12/site-packages/pymorphy2/units/base.py", line 35, in clone
    return self.__class__(**self._get_params())
                            ^^^^^^^^^^^^^^^^^^
  File "/home/paul/.local/lib/python3.12/site-packages/pymorphy2/units/base.py", line 76, in _get_params
    (key, getattr(self, key, None)) for key in self._get_param_names()
                                               ^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/paul/.local/lib/python3.12/site-packages/pymorphy2/units/base.py", line 70, in _get_param_names
    args, varargs, kw, default = inspect.getargspec(cls.__init__)
                                 ^^^^^^^^^^^^^^^^^^
AttributeError: module 'inspect' has no attribute 'getargspec'. Did you mean: 'getargs'?
import pymorphy2

# Ініціалізуємо морфологічний аналізатор
morph = pymorphy2.MorphAnalyzer(lang='uk')

def change_case(word, case):
    # Розбираємо слово
    parsed = morph.parse(word)[0]
    # Перевіряємо, чи можна відмінювати у вказаному відмінку
    if case in parsed.tag.cases:
        inflected = parsed.inflect({case})
        if inflected:
            return inflected.word
    return word

Calcium is indicated in the cell like this

=PYTHON("morphology.change_case"; A1; "родовий")

Perhaps there are other ways of implementation, without pymorphy2?

Please show me an example of calling the function.

my_value = change_case("SomeWord", "?")

I am trying with a version of LibreOffice that uses Python 3.10

I tried

change_case(lp("A3"), "родовий")

I am getting

ERROR - PyLogger: 'OpencorporaTag' object has no attribute 'cases'

I got it working for Python 3.10
Athough when I imput 'Ivanov Semenov` it outputted the same text.

pymorphy2_ex.ods (14.6 KB)

The example requries LibrePythonista and you have to pip install pymorphy2 from the menu LibrePy -> pip -> Instll Pip Package

It is CASES not cases

def change_case(word, case):
    # Розбираємо слово
    parsed = morph.parse(word)[0]
    # Перевіряємо, чи можна відмінювати у вказаному відмінку
    if case in parsed.tag.CASES:
        inflected = parsed.inflect({case})
        if inflected:
            return inflected.word
    return word

It seems the only way is to write a new custom macro.
This is an old development, written back in 2009, last published in 2011 -
Vidminky.ods (40.2 KB)
The code needs significant revision - it is written for the russian language, this macro does not suspect the existence of іїє and apostrophe. In addition, words ending in -я are processed incorrectly (some examples of errors are marked in red)

Гарне питання для людини, що народилася в Києві :smiley:

Неочікувано. А я живу в Києві
Чи не могли б ви надалі писати українською мовою? Так легше сприймається. Дякую :slight_smile:

Вже напевно завтра спробую поглянути. Можливо щось і доберу
В будь-якому випадку, дякую

It’s probably worth describing the whole process.

  1. Installed pymorphy2 (but installed it in a virtual directory, since it should work on a Windows PC as well).
  2. Taking into account that I installed it in a virtual directory, I copied the folders pymorphy2, pymorphy2-0.9.1.dist-info, pymorphy2_dicts_uk and pymorphy2_dicts_uk-2.4.1.1.1460299261.dist-info to /usr/lib/libreoffice/share/Scripts/python
  3. In the /usr/lib/libreoffice/share/Scripts/python folder, create a cod.py file with the following contents:
import pymorphy2

# Ініціалізуємо морфологічний аналізатор
morph = pymorphy2.MorphAnalyzer(lang='uk')

    def change_case(word, case):
    # Розбираємо слово
    parsed = morph.parse(word)[0]
    # Перевіряємо, чи можна відмінювати у вказаному відмінку
    if case in parsed.tag.cases:
        inflected = parsed.inflect({case})
        if inflected:
            return inflected.word
    return word

Then I needed to go to Tools > Macros > Organize Macros > Python, select the created script, and select the change_case function. But I don’t have Tools > Macros > Organize Macros > Python, I only have BASIC

So, I tried to create a Basic function that calls a Python script.
I created a new module and added the following Basic code:

Function ChangeCase(word As String, caseType As String) As String
    Dim scriptProvider As Object
    Dim pythonScript As Object

    ' Отримання доступу до Python-скриптів
    scriptProvider = ThisComponent.getScriptProvider()
    pythonScript = scriptProvider.getScript("vnd.sun.star.script:morphology.change_case?language=Python&location=user")

    ' Виклик Python-функції з параметрами
    Dim args(1) As Variant
    args(0) = word
    args(1) = caseType
    ChangeCase = pythonScript.invoke(args)
End Function

I entered =ChangeCase(A1; “родовий”) in the necessary cells, since it did not work, I also tried =ChangeCase(A1; “datv”)

And got the above errors…

I don’t know what to do next, so I created this thread.

P&s. The text was translated with the help of several services, so it may not be completely correct. I apologize in advance.