cannot get value from a cell in libreoffice 6.4.3.2 basic - libreoffice-basic

I am new to libreoffice basic, i have experience with VBA but this libreoffice is different.
I just want to get cell value but it always return zero value to me while the actuall cell can be text or number.
Here is a partial of my simple code.
Sub test_moved()
Dim Doc As Object
'worksheet
Dim sh_village As Object
Dim sh_cbc As Object
sh_village = ThisComponent.CurrentController.getActiveSheet()
'sh_village = Doc.Sheets.getByName("VillageFinal")
'sh_village = Doc.Sheets(1)
Msgbox(sh_village.getCellrangeByName("B2").getValue())
Msgbox(sh_village.getCellrangeByName("B2").Value)
Msgbox(sh_village.getCellByPosition(1,1).Value)
msgbox("The process is completed.")
End Sub
Do we need to do prior task before start coding?

The code works correctly for numeric values. However, for strings, including strings that look like a number, it will display 0 because there is no numeric value.
What you probably want instead is:
MsgBox(sh_village.getCellRangeByName("B2").getString())
Also check out Format -> Cells -> Number to see how the data is displayed in the cell. And be on the lookout for a single quote at the front of the value in the formula bar (for example '42), because that means it is a string. Delete the quote to make it a number.
i have experience with VBA but this libreoffice is different.
Yes, LibreOffice Basic is a different language from VBA and the LibreOffice API is very different from the MS Office API. Knowing that will help you use it more effectively. If possible, avoid Option Compatible, because it won't fix most problems and will only muddy the waters.

Related

MS Word function to append a Range to a document

Suppose I want to add some text at the end of a document and immediately access
it as a Range object so I can set some properties of it without affecting the preceding text. Ideally, the Range.InsertAfter
method would return a Range object which would be perfect for this, but it doesn't.
It irks me that Word must know perfectly well what range defines the result of calling InsertAfter, but on the face of it, I need to calculate it "after the fact" from the length of the inserted text, or in some other way.
So I've devised a simple-minded work-around. In pseudo-code (actually it's Delphi
code but I hope that won't discourage VBA answers) what I do is this
ARange := Document.Range
ARange.Text := 'AAA'
AEnd := ARange.End - 1 // AEnd is an integer
ARange.SetRange(AEnd, AEnd)
ARange.Text := 'XXX'
ARange.Bold := True
and it seems that I can carry on indefinitely adding blocks of text to the end
of a document by repeating the second block of code.
The line
ARange.SetRange(AEnd, AEnd)
as I understand it, seems to construct a new Range at the end of the existing one (unlike calling Collapse on an existing range),
and works fine for the simple test cases I've tried. But it leaves me wondering
whether I'm missing a trick somewhere. Is there a more direct way to append a range
to a document and get a reference to it?
PS: I should have been a bit clearer that I'm trying to do this without using the Selection object (for a variety of reasons, including the fact that you can only have one of them at at time).
There are various ways to get the Range at the end of the document. You've discovered one, but as you say, it's somewhat circuitous. My preference:
Word.Range rngEndOfDoc = Document.Content;
//Content returns a Range object and is a property, not a method like Range()
rngEndOfDoc.Collapse(Word.WdCollapseDirection.wdCollapseEnd);
rngEndOfDoc.Text = "Text at the end of the document";
Collapsing the Range is conceptually like pressing the Right (or Left) arrow key when you have a selection. So rngEndOfDoc becomes a "point" rather than containing the entire content of the main body of the document.
FWIW I can never think of a situation when I'd use EndKey for this (emulate user actions) and I'd only change the Selection when I want to leave the user at the end of the document so that he can start typing at that location.
With thanks for the three admirable answers from others, I thought I would add my
own. The following are two versions of the function that I started out wishing Word provided
natively, returning an appended range.
The first version uses the MS Word objects in the MS Word Type Library import
unit that traditionally comes with Delphi (e.g. the Word2000.Pas one), and uses "early binding" automation,
while the second version does the same thing using late binding.
function AppendRange(InputRange : Range) : Range;
var
Direction : OleVariant;
begin
Result := InputRange;
Direction := wdCollapseEnd;
Result.Collapse(Direction);
end;
function AppendRangeLB(InputRange : OleVariant) : OleVariant;
begin
Result := InputRange;
Result.Collapse(wdCollapseEnd);
end;
Usage is e.g.
AppendedRange := AppendRange(ExistingRange);
AppendedRange.Text := 'YYY';
Think of the Document.Range as the union of all the possible ranges in the main document (i.e. apart from headings, footers, floating stuff etc.). It always starts before the first character and ends after the last character (that, in my experience, is always a hidden paragraph mark). It is not possible to define another range that is after the current Document.Range or, conceptually "append" anything after Document.Range, because there is no "after" the Document.Range (it always reaches to the end).
Thus, to extend a document with new text or other inline objects, you have to insert them at the end of the Document.Range - actually just before the end, as that last, hidden, paragraph mark must still be the final character of the document. This is just what you are doing in your pseudocode.
In VBA, an empty range at the end of the document can be referenced with
Document.Range(Document.Range.End-1, Document.Range.End-1)
Attempting to define it at Document.Range.End actually raises an error, as it points to after that last (hidden) character - and that is out of the Document - that is why we need the "-1".
After getting this range we may fill it with stuff - expanding it and, logically, the Document.Range. For example, to add text at the end of the active document, one would write
ActiveDocument.Range(ActiveDocument.Range.End-1, ActiveDocument.Range.End-1).Text = "New Text"
Notice that the same "final" empty range can be reached with:
Document.Bookmarks("\EndOfDoc").Range
The following works for me in Word 15 (Office 365) using the Word 2010 type library (I'm using early binding, but it should work the same with late binding as well). Word is a TWordApplication, and aRange is a WordRange.
Word.Selection.EndKey(wdStory, wdMove);
aRange := Word.Selection.Range;
aRange.Text := 'This is new text added at the end.';

Today function equivalent in VBA in combination with countifs

I am having some problem with using a countifs formula in Excel / VBA. I have got the formula working perfect in Excel but ideally I want to use this in VBA with my form. Here is the formula in Excel which works a treat:
=COUNTIFS(Sheet1!A:A,"Place",Sheet1!K:K,"<"&TODAY())
will count the names places that are now in the past
=COUNTIFS(Sheet1!A:A,"place",Sheet1!K:K,">"&TODAY())
will count the names places that are current
I have five different Places in column A and hundreds of different dates in column K. The above formulas work well in Excel and return the correct values. I have spent hours trying to get this to work in VBA with my userform but keep getting various errors. The first part is not the problem but as soon as I get to the &today function it falls apart. From what I can see the &today function is not available in VBA and the &Date seems to be the recommendation. I have tried this but still get no where. I'm missing a trick (or several) here and I would really like to get this working in VBA rather than using the current formulas in Excel. The returned results are then displayed in textboxes on my form.
All ideas and feedback much welcome!
Second edit
================================
Thanks for the quick replies! Here is the actual code I am playing about with in VBA
'Count events by area'
Dim ListLondon As Long
ListLondon = .CountIf(Range("a1:a1998"), "London"), ("Sheet1!K1:K1998"), "<" & Date)
End With
Me.TextBox1 = ListLondon
I know the second part of the count if is all wrong regards the date - that's how I've left it for now. I am really hoping to use the current layout and a working Date / Today code at the end. Please show me what I've done wrong here!
====
oops - can see a mistake already - but the initial problem remains around the date issue. I should of used countifs as using multiple criteria.
You have to read the values of the cells to your VBA code. I recommend you to use Excel.Range object to do that. It can interpret the range like the edit line of the Excel, something like
Dim foo as Excel.Range
set foo = yourworksheet.Range("A1:B3")
Read the Date type data into VBA Date type variable by iterating through the cells.
Examine relation between the read data and the current date. Current date can be read by using the DateTime.Now function.
Increment a variable based on a decision

How to properly read a single Excel cell

I've been looking up in Google in these past days but I still can't find a good answer to this one.
Currently, this is how I do it:
For Each cell In ws.Range(fromCol, toCol)
If IsNothing(cell.Value) Then Exit For
valueList.Push(cell.Value.ToString())
Next
But when it reads a cell whose assumed data type is Time, it returns a Double value. I try to parse that value but it's not the same as expected.
How can I properly read a single Excel cell with an assumed type of Time?
As per the comment suggesting the article,
.Text is a bad idea in the sense that it will give you just the displayed string in that cell. If you use TypeName on the cell's content, for example, it will always return string regardless of any datatypes the content might be. However, if you use .Value, it will return the actual datatype name of the content of that cell.
This can prove useful to you if you're using TypeName in a comparison for instance. It saves you using conversion functions.
Take this example:
Sub Test()
Range("A1") = "True"
Debug.print(TypeName(Range("A1").Value))
Debug.print(TypeName(Range("A1").Text))
End Sub
This Output is:
Boolean
String

Word VBA - Load part of doc into variable, and run .indexOf to search

Okay, I am a Javascript programmer and VBA is driving me insane - I know nothing about it and it is like pulling teeth to find simple documentation on the simplest thing.
I'm literally trying to run a little script to auto-format a document, partly based in content.
I want to grab the third line of document, or first 100 characters, I really don't care, and run the equivalent of String().indexOf('foobar') on it, to check if that part of the document contains a string.
I cannot for the life of me find how to:
a. Load text selection into a variable.
b. Run a sane semblance to indexOf.
Can someone please help? And maybe point me to a sane VBA documentation that is not Micrsoft?
a. Load text selection into a variable.
Identify a range (Word.Range) you want and get the Text property of that range.
For instance,
dim s as string
s = ThisDocument.Paragraphs(3).Range.Text
b. Run a sane semblance to indexOf.
Is InStr no good?
msgbox InStr(s, "foobar")

How to fit VERY long condition in conditional formatting

I have a very long condition, about 3,000 characters. Access has only space for about one tenth of that.
Is there some other way to set conditional formatting on a textbox besides through the dialogue, or can I do it in VBA and, if so, HOW?
I have conditional formatting on a bunch of textboxes that trigger when the report is opened.
Would be curious to know if the VBA approach worked?
Another idea: create a hidden field on the form and set it's value based on your 3000-character condition. If you are just trying to have 1 conditional expression, you could give this hidden field a false/true or 0/1 value; if you want mulitple conditions, you could give it a value of 0, 1, 2, or 3 corresponding to the conditions you want applied. In either case, your conditional expression test(s) is(are) now trivial: [HiddenFieldName]=ConditionValue
According to Access' Help topic, the FormatConditions Collection has methods (Add, Delete, Modify) which should allow you to adjust your FormatConditions with VBA code. I've never tried, so offer no opinion as to whether this would be a practical approach for you.
I also tried to find out if there is a capacity limit for the number of characters FormatConditions can accept. I didn't find anything there.
Yes, you can manipulate Format Conditions in VBA. There's a full detailed article knowledgebase article at http://support.microsoft.com/kb/304104.
Code snippet here showing a basic example. Refer to the above link to get the VBA for AddFormats:
Public Function HighLightForeignKeys(argFieldName As String, argFieldValue As Integer)
Dim FormatCondition As String
Dim CodeReception As Integer
FormatCondition = "[" & argFieldName & "] = " & ArgFieldValue
With Me.ID
.FormatConditions.Delete
.FormatConditions.Add acExpression, , FormatCondition
.FormatConditions(0).BackColor = 16510422
AddFormats Me.ID, Me
End With
End Function
I dont know if this is what you were after, since you mentioned there was only a tiny box to enter all of your conditional text. Others have shown you VBA solutions - since you asked if that was one way to achieve it.
I have always resorted to using the "zoom" feature which is accessible via the SHIFT-F2 keystroke. Is that what you were after? I think it goes back several Access versions too.
A good set of Access shortcut keystrokes is here:
http://www.joyedaniels.com/keys_access.htm