Extract the attached zip to <profile>/user/Script/python/
Select some sheet cells. Multiple ranges on multiple sheets allowed. In case of an object selection the active cell only will listen.
Run Tools>Macros>Organize>Python...MyMacros>UpperCaseCorrection>startUpperCaseCorrection
Have fun.
The code is best viewed in some editor adjustable to Unix line feeds (LF). Writer can open it as "Text Encoded (*.txt")
It adds one listener to the range or ranges collection selected in the current controller.
The YesWeCan listener gets the active cell from the current controller, removes itself from the ranges, does what it has got to do, adds itself to the ranges. I have tested the listener with a selection of all cells on all sheets.
Unlike Basic code, the YesWeCan class keeps a reference to the document and the ranges it has been applied to. You can attach it to many spreadsheet files and get a new instances from the same class.
We get the same race condition as in Basic when 2 instances of this listener have been attached to a cell and the cell gets modified.
This is it:
Code: Select all
import uno, unohelper
from com.sun.star.util import XModifyListener
from com.sun.star.table.CellContentType import TEXT
def getActiveCell(oView):
'''Desparately missing in API. We extract from view data.'''
sData = oView.getViewData()
oSheet = oView.getActiveSheet()
as1 = sData.split(";")
lSheet = long(as1[1])
sDum = as1[lSheet +3]
delim = '/' in sDum and '/' or '+'
as2 = sDum.split(delim)
lCol = (as2[0])
lRow = (as2[1])
return oSheet.getCellByPosition(lCol,lRow)
def getRangesSelection(oView):
oSel = oView.getSelection()
if oSel.supportsService('com.sun.star.sheet.SheetCellRange'):
return oSel.queryIntersection(oSel.getRangeAddress())
elif oSel.supportsService('com.sun.star.sheet.SheetCellRanges'):
return oSel
else:
return None
class YesWeCan(XModifyListener,unohelper.Base):
def __init__(self,d,r):
self.doc = d
self.ranges = r
def modified(self,oEvent):
calling = getActiveCell(self.doc.getCurrentController())
if calling.getType() == TEXT:
self.ranges.removeModifyListener(self)
s = calling.getString()
calling.setString(s.upper())
self.ranges.addModifyListener(self)
def disposing(self,oEvent):
pass
def startUpperCaseCorrection():
document = XSCRIPTCONTEXT.getDocument()
view = document.getCurrentController()
sel = getRangesSelection(view)
if not sel: sel= getActiveCell(view)
m = YesWeCan(document,sel)
sel.addModifyListener(m)
# the helper implements all the vanilla UNO-interfaces that belong to every object.
# You may override them. See source code of unohelper module.
g_ImplementationHelper = unohelper.ImplementationHelper()
g_ImplementationHelper.addImplementation(
XSCRIPTCONTEXT,YesWeCan,'com.sun.star.util.XModifyListener',
)
g_exportedScripts = startUpperCaseCorrection,
The same code is stored in the attached source code file.
When you copy the above code you must not use the "SELECT ALL" facility of this page. It adds empty spaces which spoils Python code. Select the code manually, copy it into Writer or any decent editor and save it with UNIX line feeds (LF) and name suffix .py.
One question to hanya, please
How can I remove the attached listener from the ranges without reloading the document? I don't have any persistent object like a global var in Basic.