How do I make vba code compatible with libre office
Asked Answered
S

4

17

I have recently migrated to pclinuxos from windows and seem to like it. The only problem I am facing is that libreoffice, the default spreadsheet package is not compatible with excel macros. Below is the vba code I have:

Option VBASupport 
Sub DeleteToLeft()
    Selection.SpecialCells(xlBlanks).Delete shift:=xlToLeft
End Sub
Function SinceLastWash()
    Application.Volatile
    WashCount = 0
    WearCount = 0
    CurrentRow = Application.ThisCell.Row
    For i = 3 To 35
        If Range(Cells(CurrentRow, i), Cells(CurrentRow, i)).Value = "a" Then
            WearCount = WearCount + 1
        End If
        If Range(Cells(CurrentRow, i), Cells(CurrentRow, i)).Value = "q" Then
            WashCount = WashCount + 1
            WearCount = 0
        End If
    Next i
    SinceLastWash = WearCount
End Function
Function testhis()
testhis = Application.ThisCell.Row
End Function

Is there a way to convert this code to make it compatible with libreoffice or do I have to learn an altogether new language like python? Learning python would not be a problem but is not a solution to my problem as I have many work related files in excel which have a lot of vba code and it is not possible for me to use open office/libreoffice at work...

I just want to add that the function SinceLastWash gives the correct value in some cells where I use it and in others gives an error, #NAME?

Thanks

Straightway answered 13/7, 2014 at 15:5 Comment(0)
B
5

You must translate the portions that manipulate the document to use the UNO API. Sadly, this can be tricky depending on what your macro does. Basic statements work directly. Modifying a document generally does not.

Range(Cells(CurrentRow, i), Cells(CurrentRow, i)).Value = "a"

The Cells command returns a specific cell based on a row and column. So, you need the current row. Here is some craziness to get the active cell:

Sub RetrieveTheActiveCell()
  Dim oOldSelection 'The original selection of cell ranges
  Dim oRanges       'A blank range created by the document
  Dim oActiveCell   'The current active cell
  Dim oConv         'The cell address conversion service
  Dim oDoc
  oDoc = ThisComponent

  REM store the current selection
  oOldSelection = oDoc.CurrentSelection

  REM Create an empty SheetCellRanges service and then select it.
  REM This leaves ONLY the active cell selected.
  oRanges = oDoc.createInstance("com.sun.star.sheet.SheetCellRanges")
  oDoc.CurrentController.Select(oRanges)

  REM Get the active cell!
  oActiveCell = oDoc.CurrentSelection

  oConv = oDoc.createInstance("com.sun.star.table.CellAddressConversion")
  oConv.Address = oActiveCell.getCellAddress
  Print oConv.UserInterfaceRepresentation
  print oConv.PersistentRepresentation

  REM Restore the old selection, but lose the previously active cell
  oDoc.CurrentController.Select(oOldSelection)
End Sub

When you have the active cell, you get the cell address, and from that, you have the row. You do not need to use the range at all, since you only care about a single cell, so, you get the active sheet and then get a particular cell from the sheet.

Something like this: ThisComponent.getCurrentController().getActiveSheet().getCellByPosition(nCol, nRow).getString() = "a"

I don't feel like figuring out what this does

Selection.SpecialCells(xlBlanks).Delete shift:=xlToLeft
Burushaski answered 29/10, 2015 at 14:19 Comment(0)
C
15

From LibreOffice's online help file:

With a few exceptions, Microsoft Office and LibreOffice cannot run the same macro code. Microsoft Office uses VBA (Visual Basic for Applications) code, and LibreOffice uses Basic code based on the LibreOffice API (Application Program Interface) environment. Although the programming language is the same, the objects and methods are different.

The most recent versions of LibreOffice can run some Excel Visual Basic scripts if you enable this feature at LibreOffice - PreferencesTools - Options - Load/Save - VBA Properties.

In reality, you would most likely need to sit down with the LibreOffice API and rewrite the functionality.

Chronometry answered 15/7, 2014 at 3:18 Comment(2)
A distinguishing feature of Libre Office, the IBM fork of Open Office, the Sun version of StarWriter, was that it had some support for VBA, and ran "some Excel Visual Basic Scripts". The online help file illustrates the discontinuity of history for people shifting from Apache Open Office to Libre Office.Stagecoach
The VBA support was initially developed by Novell, but they worked together with Sun, and it shipped in OOo 3.0 (though still not complete anywhere)Groping
B
5

You must translate the portions that manipulate the document to use the UNO API. Sadly, this can be tricky depending on what your macro does. Basic statements work directly. Modifying a document generally does not.

Range(Cells(CurrentRow, i), Cells(CurrentRow, i)).Value = "a"

The Cells command returns a specific cell based on a row and column. So, you need the current row. Here is some craziness to get the active cell:

Sub RetrieveTheActiveCell()
  Dim oOldSelection 'The original selection of cell ranges
  Dim oRanges       'A blank range created by the document
  Dim oActiveCell   'The current active cell
  Dim oConv         'The cell address conversion service
  Dim oDoc
  oDoc = ThisComponent

  REM store the current selection
  oOldSelection = oDoc.CurrentSelection

  REM Create an empty SheetCellRanges service and then select it.
  REM This leaves ONLY the active cell selected.
  oRanges = oDoc.createInstance("com.sun.star.sheet.SheetCellRanges")
  oDoc.CurrentController.Select(oRanges)

  REM Get the active cell!
  oActiveCell = oDoc.CurrentSelection

  oConv = oDoc.createInstance("com.sun.star.table.CellAddressConversion")
  oConv.Address = oActiveCell.getCellAddress
  Print oConv.UserInterfaceRepresentation
  print oConv.PersistentRepresentation

  REM Restore the old selection, but lose the previously active cell
  oDoc.CurrentController.Select(oOldSelection)
End Sub

When you have the active cell, you get the cell address, and from that, you have the row. You do not need to use the range at all, since you only care about a single cell, so, you get the active sheet and then get a particular cell from the sheet.

Something like this: ThisComponent.getCurrentController().getActiveSheet().getCellByPosition(nCol, nRow).getString() = "a"

I don't feel like figuring out what this does

Selection.SpecialCells(xlBlanks).Delete shift:=xlToLeft
Burushaski answered 29/10, 2015 at 14:19 Comment(0)
M
3

In LibreOffice 4.4, the first subroutine will not work at all (I suspect due to all the variables beginning with 'xl'. The other two work perfectly if you change ThisCell to ActiveCell.

Rather than

Option VBASupport 

I am using

Option VBASupport 1
Option Compatible
Mccartney answered 1/10, 2015 at 19:33 Comment(0)
O
1

The only automatic tool I'm aware of is Business Spreadsheets (note that I have no personal or professional experience nor any affiliation with the site).

It seems specific to OpenOffice but I think it works with LibreOffice too.

In general though, you're better off doing this yourself, as the tool is far from perfect...

Onehorse answered 13/7, 2014 at 15:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.