OpenOffice.org: macro help - macros

In OOo Calc
I need to copy a column (only the values, not the format) from one sheet to another (in the same worksheet) using a macro assigned to a button.
I browsed a bit around but found nothing significant :-(

To answer the original question:
use a data array, which will be significally faster on large ranges of cells
Source = ThisWeek.getCellRangeByName("H12:H206")
source_data = Source.getDataArray()
Target = Steering.getCellRangeByName("M12:AU206").setDataArray(source_data())

OK, I could build the answer and started learning OOo Basic, which I managed to avoid until now ;-)
I give it as is.
Sub UpdateThisWeek
Dim Doc As Object
Dim ThisWeek As Object
Dim Steering As Object
Dim Source As Object
Dim Target As Object
Dim Week as Integer
Doc = ThisComponent
ThisWeek = Doc.Sheets.getByName("This week")
Steering = Doc.Sheets.getByName("Steering")
Week = Steering.getCellByPosition(6,4).Value
Source = ThisWeek.getCellRangeByName("H12:H206")
Target = Steering.getCellRangeByName("M12:AU206").getCellRangeByPosition(Week-19,0,Week-19,194)
Dim i, s
For i = 0 To 194
s = Source.getCellByPosition(0, i).Value
If s > 0 Then
Target.getCellByPosition(0, i).Value = s
Else
Target.getCellByPosition(0, i).String = ""
End If
Next i
End Sub

Related

Inserting and removing text into a textbox on a SHEET in Libreoffice calc BASIC

As I can't solve my problem I'd like to ask someone more experienced.I created simple dialog (4 fields) to let the user enter few data. After clicking "Submit" button those data should be inserted into textboxes put ON THE SHEET (not on any dialog). How to refer to those sheet texboxes in code to insert those data? Other thing is deleting those data after clicking other button "Clear". Suppose it will be similar to inserting but how this piece of code should look like?
Thanks in advance.
The trick is to create a com.sun.star.drawing.TextShape object and add it to the Draw Page of the target sheet. The following works for me. You should be able to assign it to the appropriate button on your dialog.
Sub InsertTextBox()
Dim oDocument As Object
oDocument = ThisComponent
If oDocument.SupportsService("com.sun.star.sheet.SpreadsheetDocument") Then
Dim sText As String
sText = "Blah,blah, blah!"
Dim oPosition As New com.sun.star.awt.Point
oPosition.X = 1000
oPosition.Y = 1000
Dim oSize As New com.sun.star.awt.Size
oSize.Width = 10000
oSize.Height = 5000
Dim oTextShape As Object
oTextShape = oDocument.createInstance("com.sun.star.drawing.TextShape")
oTextShape.setPosition(oPosition)
oTextShape.setSize(oSize)
oTextShape.setPropertyValue("FillStyle", "SOLID")
oTextShape.Visible = 1
' Give it a name so you can find it again when you want to delete it
oTextShape.setPropertyValue("Name", "Thingy")
Dim oDrawPage As Object
oDrawPage = oDocument.getSheets().getByIndex(0).getDrawPage()
oDrawPage.add(oTextShape)
' Set the string of the text shape AFTER adding it to the
' draw page, otherwise the text will not be set.
oTextShape.setString(sText)
End If
End Sub
In the above routine the TextShape object was given the name "Thingy". You can obviously give it any name you like, but it should be unique. To delete it, you need to loop through all the objects in the draw page, find the one that is a TextShape and has the name you gave it (in this case "Thingy") and remove it. This can be done as follows:
Sub DeleteTextBox()
Dim oDocument As Object
oDocument = ThisComponent
If oDocument.SupportsService("com.sun.star.sheet.SpreadsheetDocument") Then
Dim oDrawPage As Object
oDrawPage = oDocument.getSheets().getByIndex(0).getDrawPage()
Dim oShape As Object
Dim i As Long
For i = (oDrawPage.getCount() - 1) To 0 Step -1
oShape = oDrawPage.getByIndex(i)
If oShape.SupportsService("com.sun.star.drawing.TextShape") Then
If StrComp(oShape.getPropertyValue("Name"), "Thingy") = 0 Then
oDrawPage.remove(oShape)
End If
End If
Next i
End If
End Sub
This will delete all objects of type TextShape and named "Thingy"

Is there a way to fetch all the use case diagrams from an enterprise architect model using Java API?

I have many use case diagrams defined in a model in Enterprise Architect. The diagrams are at different levels in the hierarchy. Irrespective of where the diagram is located, is there any way to access all the use case diagrams (any diagram for that matter) present in the model using Enterprise Architect Java API?
The Java API is nothing more then a layer around the regular API, so I'm answering in general.
You can of course traverse the whole model in code to get diagrams, but that will take ages in any non-trivial model.
So what you want to do is
query the model to get all diagram guid's using EA.Repository.SQLQuery()
loop the diagram guid's and get each diagram using EA.Repository.GetDiagramByGUID()
The SQL Query
The SQL Query you need to get all use case diagram guid's is the following
select d.ea_guid from t_diagram d
where d.Diagram_Type = 'Use Case'
Getting a list of values from the query
EA.Repository.SQLQuery() returns an XML string, so you need to parse that to get a list of values. This example is an operation in VBScript that does exactly that:
function getArrayFromQuery(sqlQuery)
dim xmlResult
xmlResult = Repository.SQLQuery(sqlQuery)
getArrayFromQuery = convertQueryResultToArray(xmlResult)
end function
'converts the query results from Repository.SQLQuery from xml format to a two dimensional array of strings
Public Function convertQueryResultToArray(xmlQueryResult)
Dim arrayCreated
Dim i
i = 0
Dim j
j = 0
Dim result()
Dim xDoc
Set xDoc = CreateObject( "MSXML2.DOMDocument" )
'load the resultset in the xml document
If xDoc.LoadXML(xmlQueryResult) Then
'select the rows
Dim rowList
Set rowList = xDoc.SelectNodes("//Row")
Dim rowNode
Dim fieldNode
arrayCreated = False
'loop rows and find fields
For Each rowNode In rowList
j = 0
If (rowNode.HasChildNodes) Then
'redim array (only once)
If Not arrayCreated Then
ReDim result(rowList.Length, rowNode.ChildNodes.Length)
arrayCreated = True
End If
For Each fieldNode In rowNode.ChildNodes
'write f
result(i, j) = fieldNode.Text
j = j + 1
Next
End If
i = i + 1
Next
'make sure the array has a dimension even is we don't have any results
if not arrayCreated then
ReDim result(0, 0)
end if
end if
convertQueryResultToArray = result
End Function
Getting the diagram based on the guid's
Loop the resulting query and use Repository.GetDiagramByGUID()
In VBScript that would be something like this (supposing the results of the query are stored in the variable guidResults)
dim diagram as EA.Diagram
dim diagrams
set diagrams = CreateObject("System.Collections.Arraylist")
dim guid
for each guid in guidResults
set diagram = Repository.GetDiagramByGuid(guid)
diagrams.Add diagram
next

Resize and modify selected chart with libreoffice basic

I'm writing a macro with libreoffice basic to modify the styles and size of a selected (and only selected) chart in my spreadsheets.
After many documentation reading and many tries, I managed to have a partial solution to my problem:
Modifying all charts style
I managed to select a chart by it's indexe and modify it's styles with this macro:
Sub ModifyChart
Dim oDoc As Object
Dim oChart As Object
Dim aSize as new com.sun.star.awt.Size
oSheet = ThisComponent.sheets(0)
oCharts = oSheet.getCharts()
oChart = oCharts.getByIndex(0).getEmbeddedObject()
MsgBox oChart.ImplementationName
oChart.Title.String = "My title"
oChart.Title.CharColor = RGB(0,0,200)
oChart.Title.CharFontName = "Arial"
oChart.Title.CharHeight = 16
oChart.SubTitle.String = "My subtitle"
oChart.SubTitle.CharColor = RGB(0,0,200)
oChart.SubTitle.CharFontName = "Arial"
oChart.SubTitle.CharHeight = 12
oChart.Diagram.Wall.FillStyle = com.sun.star.drawing.FillStyle.SOLID
oChart.Diagram.Wall.FillColor = RGB(200,50,150)
oChart.Area.FillStyle = com.sun.star.drawing.FillStyle.SOLID
oChart.Area.FillColor = RGB(100,50,250)
aSize.Width=640
aSize.Height=400
oChart.setsize(aSize) ' Error occur at this point
End Sub
Problem: It's doesn't work with the selected chart and I can't resize it. The method setsize doesn't work for this kind of object. I tryed to get the parent object of the chart ( frame ? or shape ?) without success.
With ImplementationName, I found that the object is a com.sun.star.comp.sc.scshapeobj
Modifying the selected chart size
I managed to modify the selected chart size by using this macro
Sub ResizeChart
Dim oCurrSel As Object
Dim oItem As Object
Dim aSize As New com.sun.star.awt.Size
oCurrSel = ThisComponent.getCurrentSelection()
oItem = oCurrSel.getByIndex(0)
MsgBox oItem.ImplementationName
aSize.width=16000
aSize.height=12000
oItem.setsize(aSize)
End Sub
Problem: I can't access to the other styles of the chart. I tryed to find a method to get the object content without success. I also tryed to investigate the object with oItem.dbg_properties and oItem.dbg_methods but I didn't found anything useful.
With ImplementationName, I found that the object is a com.sun.star.comp.chart2.chartmodel
I have a look to the libreoffice api but I didn't find how these two kind of object are connected.
Is it possible to make what I want with libreoffice basic ?
Does anyone could explain me the hierachical structure of a libreoffice chart object (parents, childs, ...) and how to deal with it ?
Yes, you are absolutely right - parsing the current selection is not a trivial task.
Since the current selection may contain a variety of objects - Cell, CellRange, SheetCellRanges, Shapes, ShapeCollection, GraphicObjectShape and even in some cases just Text, parsing becomes similar to the game "Miner" - each next step requires additional checks (or error handling " blindly "with the help On Error Resume Next)
Your idea of ​​using ImplementationName to identify objects is generally good. But Andrew Pitonyak in 4.1. Debugging And Inspecting Macros wrote "To determine the document type, look at the services it supports ... I assume that this is safer than using getImplementationName()" and I tend to believe him.
The transition from the current selection to the embedded chart can be something like this:
Sub ModifyChartInCurrentSelection
Dim oCurrentSelection As Variant
Dim i As Long
Dim oNextElementOfSelection As Variant
Dim oEmbeddedObject As Variant
Dim oComponent As Variant
Dim aSize As New com.sun.star.awt.Size
oCurrentSelection = ThisComponent.getCurrentSelection()
If oCurrentSelection.supportsService("com.sun.star.drawing.ShapeCollection") Then
For i = 0 To oCurrentSelection.getCount()-1
oNextElementOfSelection = oCurrentSelection.getByIndex(i)
If oNextElementOfSelection.supportsService("com.sun.star.drawing.OLE2Shape") Then
Rem Size of shape (outer wrapper around the chart)
If oNextElementOfSelection.supportsService("com.sun.star.drawing.Shape") Then
aSize = oNextElementOfSelection.getSize()
aSize.Height = aSize.Height * 2 ' or any other
aSize.Width = aSize.Width / 2
oNextElementOfSelection.setSize(aSize)
EndIf
Rem Properties of EmbeddedObject
oEmbeddedObject = oNextElementOfSelection.EmbeddedObject
If Not IsEmpty(oEmbeddedObject) Then
oComponent = oEmbeddedObject.getComponent()
oComponent.getTitle().String = "Foo-bar Foo-bar Foo-bar"
Rem and other settings...
EndIf
EndIf
Next i
EndIf
End Sub

how to pass cellrange to a user defined macro paramenter

i would like to work with cellranges within my macro.
Function SumIfColor(SumRange)
Dim oRange as object
Dim oSheet as object
' Get Access to the Active Spreadsheet
oSheet = ThisComponent.CurrentController.ActiveSheet
' Get access to the Range listed in Sum Range
oRange = oSheet.getCellRangeByName(SumRange).RangeAddress
End Function
The question is how can I call this function with real cellRange object instead of String. Because getCellRangeByName works only with String variable.
Because when I call the function like this
sumifcolor(B1:B3)
I got the following error:
"Object variable not set"
I read some hint here but it did not helped me.
It is not possible to pass an actual CellRange object. One solution is to pass the row and column number, similar to the second part of #Axel Richter's answer in the link:
Function SumIfColor(lcol1, lrow1, lcol2, lrow2)
sum = 0
oCellRange = ThisComponent.CurrentController.ActiveSheet.getCellRangeByPosition(_
lcol1-1,lrow1-1,lcol2-1,lrow2-1)
For lCol = 0 To oCellRange.Columns.Count -1
For lRow = 0 To oCellRange.Rows.Count -1
oCell = oCellRange.getCellByPosition(lCol, lRow)
If oCell.CellBackColor > -1 Then
sum = sum + oCell.Value
End If
Next
Next
SumIfColor = sum
End Function
To call it:
=SUMIFCOLOR(COLUMN(B1:B3),ROW(B1),COLUMN(B3),ROW(B3))
The sum will be recalculated whenever a value in the range B1:B3 is changed, because of COLUMN(B1:B3). However, apparently changing only the color of a cell does not cause it to be recalculated.

How to end a Basic function properly

I'm trying to write a function in Basic for LibreOffice Calc to get the first letter of each word of the selected cell using the following code:
Function GetFirstLetters(rng) As String
Dim arr
Dim I As Long
arr = Split(rng, " ")
If IsArray(arr) Then
For I = LBound(arr) To UBound(arr)
GetFirstLetters = GetFirstLetters & Left(arr(I), 1)
Next I
Else
GetFirstLetters = Left(arr, 1)
End If
End Function
And it works correctly, unless I try to execute it again, then it seems that the new result gets appended to that of any previous execution and it will return both strings together, example:
It also doesn't matter if I delete some or even all cells, or if I call it using an empty cell or even in another page, it will always append the result to the previous one:
Why does this happen? How can I fix this behaviour?
I don't know anything about Basic, so please don't bash on me if this is something very simple.
The original function is this:
Function GetFirstLetters(rng As Range) As String
'Update 20140325
Dim arr
Dim I As Long
arr = VBA.Split(rng, " ")
If IsArray(arr) Then
For I = LBound(arr) To UBound(arr)
GetFirstLetters = GetFirstLetters & Left(arr(I), 1)
Next I
Else
GetFirstLetters = Left(arr, 1)
End If
End Function
And I got it from here: http://www.extendoffice.com/documents/excel/1580-excel-extract-first-letter-of-each-word.html.
The code you have found is VBA for Excel. Openoffice or Libreoffice uses StarBasic, not VBA. This is similar but not equal. So you can't simply use the same code as in Excel.
First difference is, there is no Range object. This you have noticed and have used rng as an Variant.
But another difference is, function names are like variable names in the global scope. And they will not be reseted if the function is called again. So in StarBasic we better do:
Function GetFirstLetters(sCellValue as String) As String
Dim arr As Variant
Dim I As Long
Dim sResult As String
arr = Split(sCellValue, " ")
If IsArray(arr) Then
For I = LBound(arr) To UBound(arr)
sResult = sResult & Left(arr(I), 1)
Next I
Else
sResult = Left(arr, 1)
End If
GetFirstLetters = sResult
End Function
sResult is reseted (new Dimed) every time the function is called. So even the function's return value.