Cell content inside formula - openoffice-calc

Is it possible to place the content of a cell inside a formula. By formula I mean the math formula editor (insert->object->formula).

To the best of my knowledge, there is no way to reference a cell from a formula. Math formula editor has no knowledge about OO Calc. However, you can create a new formula whenever needed using macros.
Follow thesse steps to make it work:
Put the math formula you want to insert to a cell. For example, put some numbers to cells A1, A2, A3 and put the following to cell C3:
=CONCATENATE("{";A1;"}";"over {";A2;" `+` ";A3;"}";" `=` ";A4).
This will generate something like {1} over {2 `+` 3} `= in C3
Create a macro from the code below. In OO Calc, select
Tools > Macros > Organize Macros > OpenOffice.org Basic > My Macros > Standard
Create a new macro and paste the code below.
Now you can run macro using Tools > Macros > Run Macro. Run either insertFormula which inserts math formula generated from cell C3, or addFormulaListener which will register a listener and regenerate the formula for you whenever contents of C3 changes.
Here is the code. It contains constants formulaCellFrom and formulaCellTo, which specify which cell has the math formula source and which is the target cell where the generated formula object shall be placed. Note that the target cell must be large enough for the generated formula, otherwise the macro won't delete cell's old content when regenerating the formula.
const formulaCellFrom As String = "$C$1"
const formulaCellTo As String = "$C$10"
rem ----------------------------------------------------------------------
rem Adds listener for changes of the math formula
sub addFormulaListener
dim oSheet as Object
dim oCell as Object
rem go to cell containing markup
oSheet = ThisComponent.CurrentController.ActiveSheet
oCell = oSheet.getCellRangeByName(formulaCellFrom)
rem add listener
oListener = CreateUnoListener( "formulaListener_", "com.sun.star.chart.XChartDataChangeEventListener" )
oCell.addChartDataChangeEventListener(oListener)
end sub
rem ----------------------------------------------------------------------
rem Listener for cell changes
sub formulaListener_chartDataChanged
dim oCell as Object
rem remember current cursor position
oCell = ThisComponent.CurrentSelection
rem call insertFormula
call insertFormula
rem restore cursor position
ThisComponent.CurrentController.select(oCell)
end sub
rem ----------------------------------------------------------------------
rem Creates a math formula from text in cell C1 and inserts it into cell C10
sub insertFormula
dim document as object
dim dispatcher as object
rem get access to the document
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
rem go to cell containing markup and copy it
dim fromCellArgs(0) as new com.sun.star.beans.PropertyValue
fromCellArgs(0).Name = "ToPoint"
fromCellArgs(0).Value = formulaCellFrom
dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, fromCellArgs())
dispatcher.executeDispatch(document, ".uno:Copy", "", 0, Array())
rem go to cell where I want the formula displayed
dim toCellArgs(0) as new com.sun.star.beans.PropertyValue
toCellArgs(0).Name = "ToPoint"
toCellArgs(0).Value = formulaCellTo
dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, toCellArgs())
rem delete previous content
dim deleteArgs(0) as new com.sun.star.beans.PropertyValue
deleteArgs(0).Name = "Flags"
rem flags: A = All, S = String, V = Value, D = DateTeim, F = Formula, ...
rem ... N = Notes, T = Formats, O = Objects
deleteArgs(0).Value = "AO"
dispatcher.executeDispatch(document, ".uno:Delete", "", 0, deleteArgs())
rem open Star.Math
oDesk = createUnoService ("com.sun.star.frame.Desktop")
dispatcher.executeDispatch(document, ".uno:InsertObjectStarMath", "", 0, Array())
rem get access to the document
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
rem paste clipboard using Array() as place-holder for variable name
dispatcher.executeDispatch(document, ".uno:Paste", "", 0, Array())
rem exit Star.Math
dispatcher.executeDispatch(document, ".uno:TerminateInplaceActivation", "", 0, Array())
end sub
The code was adapted from this question. Apparently, the macro must be created in My Macros and doesn't work when embedded in the spreadsheet (security measure? it just didn't work for me). The source and target cells are hardcoded but you can modify the macro to suit your needs. I'm not skilled in Visual Basic but such modifications should be easy.

Related

Copy certain number of Columns in a row

I update sheets on a weekly basis, I import an external file (starting point) using the code below import selected Columns to sheet2- all is good.
Sub Copy_Specific_Columns_ToAnother_Sheet()
Sheets("Data").Range("C:C").Copy Sheets("Sheet2").Range("B:B")
Sheets("Data").Range("D:D").Copy Sheets("Sheet2").Range("C:C")
Sheets("Data").Range("B:B").Copy Sheets("Sheet2").Range("D:D")
Sheets("Data").Range("I:I").Copy Sheets("Sheet2").Range("E:E")
Sheets("Data").Range("K:K").Copy Sheets("Sheet2").Range("F:F")
Sheets("Data").Range("H:H").Copy Sheets("Sheet2").Range("G:G")
Sheets("Data").Range("J:J").Copy Sheets("Sheet2").Range("H:H")
Sheets("Data").Range("AF:AF").Copy Sheets("Sheet2").Range("I:I")
'Clean up sheet with formatting
ActiveSheet.UsedRange.Font.Size = 12
ActiveSheet.UsedRange.Font.Name = "Calibri"
ActiveSheet.UsedRange.EntireColumn.AutoFit
ActiveSheet.UsedRange.EntireRow.AutoFit
Range("a1").EntireRow.RowHeight = 45
Range("a2").EntireRow.RowHeight = 30
End Sub
On sheet2 I create a unique identifier (non macro) and import the sheet 2 details to a Master sheet where I make edits from Columns K onwards.
The code below looks for the unique identifier and pull in new rows
** However when new rows are added it means that my notes from column L onwards are deleted every time i update.
Can the code below be modified so that new rows only update to a specific column (say upto K) leaving my additional notes and entries untouched.. ? ("A" column has the unique identifier, MACRO looks for changes and pulls in new rows)
Sub Update_Data()
Dim wsSource As Worksheet
Dim wsDest As Worksheet
Dim recRow As Long
Dim lastRow As Long
Dim fCell As Range
Dim i As Long
'Define our worksheets
Set wsSource = Worksheets("Sheet2")
Set wsDest = Worksheets("Master")
Application.ScreenUpdating = False
recRow = 1
With wsSource
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = 2 To lastRow
'See if item is in Master sheet
Set fCell = wsDest.Range("A:A").Find(what:=.Cells(i, "A").Value, lookat:=xlWhole, MatchCase:=False)
If Not fCell Is Nothing Then
'Record is already in master sheet
recRow = fCell.Row
Else
'Need to move this to master sheet after last found record
.Cells(i, "A").EntireRow.Copy
wsDest.Cells(recRow + 1, "A").EntireRow.Insert
recRow = recRow + 1
End If
Next i
End With
'Code clean up
Application.CutCopyMode = False
Application.ScreenUpdating = True
'Clean up sheet with formatting
ActiveSheet.UsedRange.Font.Size = 12
ActiveSheet.UsedRange.Font.Name = "Calibri"
ActiveSheet.UsedRange.EntireColumn.AutoFit
ActiveSheet.UsedRange.EntireRow.AutoFit
Range("a1").EntireRow.RowHeight = 45
Range("a2").EntireRow.RowHeight = 30
End Sub

Excel | Get all column/row names in which a specific text is as a list

It is difficult for me to describe the problem in the title, so excuse any misleading description.
The easiest way to describe what I need is with an example. I have a table like:
A B C
1 x
2 x x
3 x x
Now what I want is the formula in a cell for every single column and row with each of the column or row name for every x that is placed. In the example like:
A B C
1,2 2,3 3
1 A x
2 A, B x x
3 B, C x x
The column and row names are not equivalent to the excel designation. It works with an easy WHEN statement for single cells (=WHEN(C3="x";C1)), but not for a bunch of them (=WHEN(C3:E3="x";C1:E1)). How should/can such a formula look like?
So I found the answer to my problem. Excel provides the normal CONCATENATE function. What is needed is something like a CONCATENATEIF (in German = verkettenwenn) function. By adding a module in VBA based on a thread from ransi from 2011 on the ms-office-forum.net the function verkettenwenn can be used. The code for the German module looks like:
Option Explicit
Public Function verkettenwenn(Bereich_Kriterium, Kriterium, Bereich_Verketten)
Dim mydic As Object
Dim L As Long
Set mydic = CreateObject("Scripting.Dictionary")
For L = 1 To Bereich_Kriterium.Count
If Bereich_Kriterium(L) = Kriterium Then
mydic(L) = Bereich_Verketten(L)
End If
Next
verkettenwenn = Join(mydic.items, ", ")
End Function
With that module in place one of the formula for the mentioned example looks like: =verkettenwenn(C3:E3;"x";$C$1:$K$1)
The English code for a CONCATENATEIF function should probably be:
Option Explicit
Public Function CONCATENATEIF(Criteria_Area, Criterion, Concate_Area)
Dim mydic As Object
Dim L As Long
Set mydic = CreateObject("Scripting.Dictionary")
For L = 1 To Criteria_Area.Count
If Criteria_Area(L) = Criterion Then
mydic(L) = Concate_Area(L)
End If
Next
CONCATENATEIF = Join(mydic.items, ", ")
End Function

Changing programmatically print area in OpenOffice Calc

I'm creating a Calc document on the fly with vb6. I need to repeat 1 row and 1 column in every page when i print it.
This is the code:
Dim mPrintOptions(2) As Object
Dim OO_Dispatcher As Object
Set OO_Dispatcher = oServiceManager.createInstance("com.sun.star.frame.DispatchHelper")
Set mPrintOptions(0) = MakePropertyValue(oServiceManager, "PrintArea", "")
Set mPrintOptions(1) = MakePropertyValue(oServiceManager, "PrintRepeatRow", "$A$2")
Set mPrintOptions(2) = MakePropertyValue(oServiceManager, "PrintRepeatCol", "$A$1")
OO_Dispatcher.executeDispatch oDeskTop, ".uno:ChangePrintArea", "", 0, mPrintOptions
I've got this code making a macro in a saved document.
Service manager and Desktop objects are previously instanced. The document is being created fine, but when I send it to the printer it does not repeat the row and the column I specified above.
I've found my solution here:
https://wiki.openoffice.org/wiki/ES/Manuales/GuiaAOO/TemasAvanzados/Macros/StarBasic/TrabajandoConCalc/Imprimiendo
My code finally got like this:
Dim OO_TitulosR As Object
Dim OO_ActiveSheet As Object
Set OO_TitulosR = OO_Document.Bridge_getStruct("com.sun.star.table.CellRangeAddress")
Set OO_ActiveSheet = OO_Document.getCurrentController.getActiveSheet
OO_TitulosR.StartColumn = 0
OO_TitulosR.EndColumn = 0
OO_TitulosR.StartRow = 1
OO_TitulosR.EndRow = 1
OO_ActiveSheet.setTitleColumns OO_TitulosR
OO_ActiveSheet.setTitleRows OO_TitulosR

"if then statement in VBA to fill cell with number"

"if then statement in VBA" I'm writing a program that puts a number in a cell in Excell if a variable reaches a certain value. I understand how to declare variables but I don't know how to tell excel to write x if A1 =34. Thanks
Add a listener to your worksheet to capture a Range. You can make the range [A1] if you are only watching a specific column/row, or you can add a range like I have below.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
Set KeyCells = Range("A:A")
If Not Application.Intersect(KeyCells, Range(Target.Address)) _
Is Nothing Then
If Target.Value = "34" Then
Cells(Target.Row, 2) = "X"
Else
Cells(Target.Row, 2) = ""
End If
End If
End Sub
Change "x" to if you want variable x and not literal x.
If your goal is to change the value of the cell to "X" (Literal X), and you are not having macros run constantly or with each cell change, you can use the following function (or similar) in each cell in which you have a conditional.
See the Microsoft support on this topic https://support.microsoft.com/en-us/kb/213612
It's not clear what you wish to do, but let's say you want to write the current value of your variable, x, into cell B2... if cell A1 is 34.
In the above case, you would do this:
If [a1] = 34 then [b2] = x
Private Sub CommandButton1_Click()
Dim lr As Long
lr = Worksheets("New").Range("A" & Rows.Count).End(xlUp).Row
Worksheets("New").Range("T2").Formula = "=LEFT(B2,2)"
Worksheets("New").Range("T2").AutoFill Destination:=Worksheets("New").Range("T2:T" & lr)
Worksheets("New").Range("U2").Formula = "=(T2&0&0)"
Worksheets("New").Range("U2").AutoFill Destination:=Worksheets("New").Range("U2:U" & lr)
Worksheets("New").Range("V2").Formula = "=IF(AND(a2=A1,U2=U1),"",A2")" (HOW TO AUTO FILL THIS FORMULA IN A CELL)
Worksheets("New").Range("V2").AutoFill Destination:=Worksheets("New").Range("V2:V" & lr)
End Sub

How to normalize Excel cell data

I am getting the data from an external source, and I need to normalize the cells.
like this:
A
32.1342244,31.1322214,0
35.12331299999999,12.14324553333333,0
..
..
And I would like Row A to be in the form of two numbers (instead of three) and with the mantissa with 8 digits max. so the above data would look like this:
A
32.1342244,31.1322214
35.12331299,12.14324553
..
..
How can I do this? Is there a way to use a regexp for that?
Can this be done in a way to simply sanitize the data and not copy it from one place to another?
Select the cells you wish to process and run this tiny macro:
Sub Normalize()
Dim r As Range, ary
For Each r In Selection
ary = Split(r.Value, ",")
ary(0) = Format(ary(0), "0.00000000")
ary(1) = Format(ary(1), "0.00000000")
r.Value = ary(0) & "," & ary(1)
Next r
End Sub