OpenOffice Calc Merged Cell properties - vba

I've been searching the web for hours and I can't find an answer for this. I can identify that a given cell is merged but I need to know how many rows are included in the merged cell.
Function aac_MergeRowCount(intStartCol as Integer, intStartRow as Integer)
oSheet = ThisComponent.CurrentController.ActiveSheet
oCell = oSheet.GetCellByPosition(intStartCol, intStartRow)
strData = oCell.GetString()
If oCell.IsMerged Then
strCopy = strData
strWasMerged = True
iCount = oCell.GetNumberOfRows()
End If
aac_MergeRowCount = iCount
End Function

Turns out I just needed to ditch OpenOffice and use Excel. The command I was needing is:
strData = oSheet.Cells(r, c).MergeArea.Rows.Count
Which did not work in OpenOffice

Related

LibreOffice Calc: Can I get the cell address from VLOOKUP?

I'm using VLOOKUP, in Calc, like this:
VLOOKUP(B11,G2:J7,4,0)
Normally when any of us uses this, we want to get the value in the cell this function finds. In this case, rather than the value, I'd like to get a string with the cell address in it instead or the row and column of that cell. For instance, if I have a double precision floating point value of 30.14 in cell J5 and that's the answer, rather than having it return 30.14, I want it to return something like "J5" or 9,4 or some other way for me to read the result in a macro.
I've tried using =ADDRESS() and =CELL("address", ) but I'm getting errors (=CELL() gives me '#REF!').
EDIT: I'm using this routine as a wrapper around VLOOKUP with a table of floating point numbers (which is why it returns a DOUBLE instead of getting the cell value as a STRING or something else). All I have to do is pass it the column I want to get the data from:
Function getLookup(valColumn as Integer) as Double
oDoc = ThisComponent
oSheet = oDoc.Sheets (workSheet)
rangeInfo = lookupTopLeft + ":" + lookupBottomRight
cellRange = oSheet.getCellRangeByName(rangeInfo)
oCell = oSheet.GetCellByPosition(dataCellColumn, dataCellRow)
searchValue = oCell.getString()
Mode = 0
svc = createUnoService( "com.sun.star.sheet.FunctionAccess" )
args = Array(searchValue, cellRange, valColumn, Mode)
getLookup = svc.callFunction("VLOOKUP", args)
End Function
Note I'm using some local variables in this. They're private, for the module only, so I don't have to change cell references in multiple places while I'm working on designing my spreadsheet. "lookupTopLeft" and "lookupBottomRight" are "G2" and "J7", the top left and bottom right cells for the data I'm working with. "dataCellColumn", and "dataCellRow" are the column and row coordinates for the source for the key I'm using in VLOOKUP.
(#JohnSUN, I think this may be modified from an answer you provided somewhere.)
I'd like to be able to do a similar wrapper routine that would return the column and row of a cell instead of the value in the cell.
One of many possible options:
Option Explicit
Const lookupTopLeft = "G2"
Const lookupBottomRight = "J7"
Const dataCellColumn = 1
Const dataCellRow = 10
Const workSheet = 0
Function getCellByLookup(valColumn As Integer) As Variant
Dim oSheet As Variant, cellRange As Variant, oCell As Variant
Dim oColumnToSearch As Variant
Dim oSearchDescriptor As Variant
Dim searchValue As String
Dim nRow As Long
oSheet = ThisComponent.getSheets().getByIndex(workSheet)
cellRange = oSheet.getCellRangeByName(lookupTopLeft + ":" + lookupBottomRight)
searchValue = oSheet.GetCellByPosition(dataCellColumn, dataCellRow).getString()
Rem If we are looking not for a value, but for a cell,
Rem then using VLOOKUP is unnecessary, a simple Find is enough
oColumnToSearch = cellRange.getCellRangeByPosition(0, 0, 0, _
cellRange.getRows().getCount()-1) ' Resize full range to one first column
Rem Set search params
oSearchDescriptor = oColumnToSearch.createSearchDescriptor()
oSearchDescriptor.setSearchString(searchValue)
oSearchDescriptor.SearchType = 1 ' Search in Values!
Rem Try to find searchValue in oColumnToSearch
oCell = oColumnToSearch.findFirst(oSearchDescriptor)
If Not IsNull(oCell) Then ' Only if the value was found
nRow = oCell.getRangeAddress().StartRow
Rem Offset oCell to valColumn
oCell = cellRange.getColumns().getByIndex(valColumn-1).GetCellByPosition(0,nRow)
getCellByLookup = Replace(oCell.AbsoluteName, "$", "")
Else ' If the value from B11 is not found - warn about it
getCellByLookup = "Not found"
EndIf
End Function

Excel conversion of text containing ranges--numeric to alpha-numeric

I would like to convert a range of numbers (and single digits) from a number-only format to alpha-numeric format. Entire statement is in a single, excel cell and would like the converted version to be in a neighboring cell.
As an example:
Assuming 1-24=B1-B24
Assuming 25-48=C1-C24
INPUT—
screen 1-3,5,7-9,11-30,32-37,39-40,41,44-46
DESIRED OUTPUT (all acceptable)
screen B1-B3,B5,B7-B9,B11-C6,C8-C13,C15-C16,C17,C20-C22
OR
screen B1-B3,B5,B7-B9,B11-B24,C1-C6,C8-C13,C15-C16,C17,C20-C22
OR
screen B1-B3,B5,B7-B9,B11-B24
screen C1-C6,C8-C13,C15-C16,C17,C20-C22
Using excel functions is proving quite cumbersome so excel macro would be better. I've looked for examples of requested conversion but haven't found anything.
Any help is greatly appreciated.
Cheers,
Bob
Hey here is a solution that i tested out. Not sure if "screen" needs to be in the string or not. Let me know and I will tweak it if that's the case.
Its a user defined function. So drop this vba in a module and then go to a worksheet and type in "=AlphaConvert(" + the cell reference.
Assumption here is that only one cell will be referenced at a time.
Last this could easily be converted to a sub routine and probably run a bit faster than the function.
Public Function AlphaConvert(TargetCell As Range)
Dim v As Long
Dim vArr() As String
Dim i As Long
Dim iArr() As String
Dim a As String
vArr = Split(TargetCell.Value, ",")
For v = LBound(vArr) To UBound(vArr)
If InStr(vArr(v), "-") > 0 Then
iArr = Split(vArr(v), "-")
For i = LBound(iArr) To UBound(iArr)
If i = LBound(iArr) Then
a = AlphaCode(iArr(i))
Else
a = a & "-" & AlphaCode(iArr(i))
End If
Next i
vArr(v) = a
Else
vArr(v) = AlphaCode(vArr(v))
End If
If v = LBound(vArr) Then
AlphaConvert = vArr(v)
Else
AlphaConvert = AlphaConvert & "," & vArr(v)
End If
Next v
End Function
Private Function AlphaCode(Nbr As Variant)
Select Case Nbr
Case 1 To 24
AlphaCode = "B" & Nbr
Case Else
AlphaCode = "C" & Nbr - 24
End Select
End Function

Knowing the assigned name of a cell instead of the "A1" name

Context:
I have several lists in my sheet (1 column wide, 1-10 rows long). When I right click a cell in these lists, I can do several options, that all work well. I have given a name to the cell at the top of each of these lists (ex. Cell A1 has been given the name cell_1, B10 is names cell_2, etc).
I would like to know if the cell I am right clicking on is the one at the top of the list; is it named "cell_(number)"? If it is not, it checks the cell on top of that one. Does it have a name that starts with "cell_"? If not, check the one on top, etc. Until I can figure out the user clicked on an element of WHICH list.
TL;DR The actual question
I can use ActiveCell.Address, which gives me something like "A1" whether or not I have assigned a name to that cell. ActiveCell.Name gives "Sheet1!A1", so it's not much better. Any idea how to get it to return the name I have assigned instead?
Create a UDF to test the application names, it's less efficient but contains error handling within the function itself:
Sub SO()
'// Example how to call function
Debug.Print GetCellName(Range("A1"))
End Sub
Function GetCellName(myCell As Excel.Range) As Variant
Dim nameCheck As Variant
For Each nameCheck In Application.Names
If Replace(Replace(Replace(nameCheck, "=", ""), "'", ""), "!", "") = _
CStr(myCell.Parent.Name & myCell.Address) Then
GetCellName = CStr(nameCheck.Name)
Exit Function
End If
Next
GetCellName = CVErr(Excel.xlErrName)
End Function
Note you can also use this function in a worksheet cell like so:
=GetCellName(A1)
Perhaps this would work. This function returns the names assigned to a cell (or bigger range for that matter). If there's more than one name, it returns it as an array for array formula...or the user can supply an index to return only the desired name position
Public Function CellIsInRangeNames(sheetname As String, checkRange As Range, Optional itemNumber As Variant) As Variant
Dim oNM As Name
Dim oSht As Worksheet
Dim isect As Range
Dim namesCollection() As Variant
Set oSht = Worksheets(sheetname)
Dim i As Integer
i = -1
For Each oNM In oSht.Names
Set isect = Application.Intersect(Range(oNM.Name), checkRange)
If Not isect Is Nothing Then
i = i + 1
ReDim Preserve namesCollection(0 To i)
namesCollection(i) = CStr(oNM.Name)
End If
Next oNM
If i = -1 Then
'didn't find any
CellIsInRangeNames = xlErrName
ElseIf Not IsMissing(itemNumber) Then
'user wanted this instance only
If (itemNumber - 1 > UBound(namesCollection)) Or (itemNumber - 1 < LBound(namesCollection)) Then
CellIsInRangeNames = xlErrValue
Else
CellIsInRangeNames = namesCollection(itemNumber - 1)
End If
Else 'here's the list as an array
CellIsInRangeNames = namesCollection
End If
End Function

Excel VBA: If A2="a","b","c",etc... then B2="aa"?

I'm attempting to take the text in each cell of column A and assign a value to each cell in column B depending on the text in column A. For example, I have a list of versions that are identified by four-letter abbreviations of cities, and all of those versions are regionally assigned to different factories to be produced. So let's say I have an "AUST", "DAFW", "HOUS", and more versions all assigned to the location of "ARLINGTON". How would I most concisely use VBA to automate that once I have all the versions plugged in? Something like
If A2="AUST" Then
B2="ARLINGTON"
ElseIf A2="DAFW" Then
B2="ARLINGTON"
I suppose something like this would work, however I can't believe that there's not a faster and more concise way. Does this make any sense? I've been pulling my hair out for about a week now trying to figure this out... Thanks for any help!
This is a little simpler using OR:
If A2="AUST" OR A2="DAFW" Then
B2="ARLINGTON"
ElseIf A2 = "ABCD" OR A2 = "WZYZ" Then
B2="SOMETHING"
'ETC...
However, if you are iterating over column A, the variable "A2" is strange. But I am not sure how you are doing this. Maybe supply more code and we can help you more.
This could be done with excel formulas as well, though I always prefer to use VBA. This should work the way you want :
Sub yourFunk()
Set wb = ThisWorkbook
Set ws = wb.Sheets(1)
arlington = Array("AUST", "DAFW", "HOUS")
otherLocation = Array("XXXX", "YYYY", "ZZZZ")
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
For x = 2 To lastRow
If stringIsInArray(ws.Cells(x, 1), arlington) Then
ws.Cells(x, 2) = "ARLINGTON"
ElseIf stringIsInArray(ws.Cells(x, 1), otherLocation) Then
ws.Cells(x, 2) = "OTHER LOCATION"
End If
Next x
End Sub
Function stringIsInArray(stringToBeFound As String, arr As Variant) As Boolean
stringIsInArray = (UBound(Filter(arr, stringToBeFound)) > -1)
End Function
If you need me to explain the code, please do let me know :)
The fastest way is to use Dictionary.
Let's say, your data is present in the following range:
A2 = "AUST"
A3 = "DAFW"
Now, check this code:
'Needs reference to Microsoft Scripting Runtime
Sub Translate()
Dim dic As Dictionary
Dim i As Integer, sTmp As String
Set dic = New Dictionary
dic.Add "AUST", "ARLINGTON"
dic.Add "DAFW", "ARLINGTON"
For i = 2 To 3
sTmp = ThisWorkbook.Worksheets(1).Range("A" & i)
Debug.Print sTmp, "-", dic(sTmp)
Next
Set dic = Nothing
End Sub
Note: This code is just an example!
For further information please see: https://msdn.microsoft.com/en-us/library/office/gg251825.aspx

Saving VBA Dictionary object in Excel

As part of an Excel Workbook Template a Dictionary object (from the Scripting Runtime Library) is created and added to. Is it possible to save this in some way along with the Workbook such that it is available on starting up the Workbook, or should I just export the data to a worksheet and save it, then reload it in the next time?
I reckon a worksheet is the best bet. You might like to use the very hidden option, which means the sheet can only be made visible by code.
For example:
Worksheets("System").Visible = xlVeryHidden
Why not save it to a file?
Sub Save_Dict(aDict As Scripting.Dictionary, FileitAs As String, Data_ID As String)
Dim one, SaveStr() As String, s As Long
ReDim SaveStr(aDict.Count)
SaveStr(0) = Data_ID
s = 0
For Each one In aDict
s = s + 1
SaveStr(s) = one & vbBack & aDict(one)
Next one
Write Join(SaveStr, vbCrLf)) to FileitAs 'Method of choice
End Sub
'~~~~~~~~~~~~~~~~
sub Get_Dict(aDict as Scripting.Dictionary, FiledAs as String, Data_ID as String) as Long
Dim one, SavedString, nLng as long, i as integer
Read SavedString from FiledAs - 'Method of choice
SavedString = split(SavedString, vbCrLf)
If Ubound(SavedString) =>0 then
Data_ID = SavedString(0)
For nLng = 1 to ubound(SavedString)
i = instr(SavedString(nLng),vbBack)
adict.add left(SavedString(nLng),i-1, Mid(SavedString(nLng),i+1)
next Nlng
End If
End Sub