Within a VB6 form, I'm using an SCGrid object were the cells are editable by means of a textbox.
I suppose the grid control creates a TextBox object as soon as the user clicks a cell.
I need a reference to this TextBox.
In particular, when the user presses the [Left] or [Right] key, I need the current position of the cursor within the textbox. I can then simply call TextBox.SelStart.
Does anybody know how to get the control used when editing a cell?
I figured it out myself:
' Declaration needed for getting the current position of the cursor
Private Type Point
x As Long
y As Long
End Type
Private Declare Function GetCaretPos Lib "user32" (ByRef lpPoint As Point) As Long
' This function returns the position of the cursor within the cell currently being edited as a TextBox
' The value is expressed as the number of characters preceeding the position
Private Function GetCaretPosition() As Integer
' Variables
Dim position As Point
Dim result As Long
Dim contents As String
' Get position
result = GetCaretPos(position)
' Convert it into number of characters
' I figured out the factor 15 by trial and error
' Don't know where it comes from but it seems independent of the font size
contents = myGrid.Text(row_gvar, column_gvar)
result = 0
While ((result < Len(contents)) And _
(position.x > (grid_gvar.Parent.TextWidth(Left(contents, result)) / 15)))
result = result + 1
Wend
' Done
GetCaretPosition = result
End Function
Related
How do you search for text in module using dxl script. Once found I want to highlight the object in which the text was found
The corresponding DXL Perm for highlighting is
Declaration
bool highlightText(Object, int start, int stop, int colIndex, bool isHeading)
Operation
Highlights text in the given module, in the given column from cursor position start to cursor position stop.
Example
//Highlights the first 10 characters of the current objects heading
highlightText(current Object, 10, 20, 1, true)
Note that only one object can be highlighted at one time.
Look at chapter "Object searching" in the DXL manual for other perms you might need in this context.
For searching I would suggest the perm contains
Declaration
int contains(Buffer b, char ch [,int offset])
int contains(Buffer b, string word, int offset)
Operation
The first form returns the index at which the character ch appears in buffer b, starting from 0. If present, the value of
offset controls where the search starts. For example, if offset is 1, the search starts from 2. If offset is not
present, the search starts from 0. If ch does not appear after offset, the function returns -1.
The second form returns the index at which string word appears in the buffer, starting from 0, provided the string is
preceded by a non-alphanumeric character. The value of the mandatory offset argument controls where the search
starts. If word does not appear after offset, the function returns -1.
I have a spreadsheet containing data in lines on several sheets. These sheets are named arbitrarily (not sheet1 sheet2 nor any similar scheme).
I need to extract some info from one of the lines of the current sheet (I give the number of the line in an input box), then put this info on another sheet to format it, then print that formatted sheet, and finally go back to the initial sheet I was on (one of those containing data).
So far I have come up with this code: (I omit the line selection and data copying because that works)
' Sheets("facture").PrintOut
Dim oDoc as Object
oDoc=ThisComponent
Dim sPrefix$ ' Prefix used to identify the print listener routines.
Dim sService$ ' Print listener service name
sPrefix="print_listener_"
sService="com.sun.star.view.XPrintJobListener"
If NOT oDoc.sheets().hasByName("facture") Then
MsgBox "Le document n'a pas de page nommée 'facture'"
Else
Dim oSheets
oSheets = oDoc.Sheets
Dim currentSheet
currentSheet = oDoc.getcurrentcontroller.activesheet
oDoc.currentController.setActiveSheet(oSheets.getByName("facture"))
oPrintListener=CreateUnoListener(sPrefix,sService)
oDoc.addPrintJobListener(oPrintListener)
'oPrintJobListnerDoc=oDoc
oDoc.Print(Array())
wait 12000
oDoc.currentController.setActiveSheet(currentSheet)
However, when I run it, the data is correctly formated on my output sheet, but the VB window pops up with 'BASIC runtime error: property or meethod not found: $(ARG1)'.
If I remove the 'wait 12000' and 'oDoc.currentController.setActiveSheet(currentSheet)' then the data is printed correctly but Calc stays on the output sheet, and doesn't get back tot the initial sheet I was on (obviously).
If I only remove the 'wait 12000', nothing happens, and the data is not printed.
Can anybody help? Thanks!
The general principle of waiting for the end of printing can be expressed as follows
REM ***** BASIC *****
Public Statex1 As Integer ' Through this variable, the event handling procedure will notify the main program
Public oPrintJobListnerDoc As Variant
Sub PrintOutFacture()
Dim oDoc As Variant
oDoc=ThisComponent
Statex1=0
oPrintJobListnerDoc = CreateUnoListener("print_listener_", "com.sun.star.view.XPrintJobListener")
oDoc.addPrintJobListener(oPrintJobListnerDoc)
Rem ...Prepare the print - fill the cells with the desired values, format, define the print area, etc.
oDoc.Print(Array()) ' It might not be an empty array, but a whole bunch of print options!
While Statex1=0 ' 1 = Printing completed, 3 = Print canceled
Wait 100
Wend
oDoc.removePrintJobListener(oPrintJobListnerDoc)
Rem ...Post-Print Actions - Switch the sheet, close the document, or do something else
End Sub
Sub print_listener_printJobEvent(oEvent As Variant)
Statex1 = oEvent.State ' Pass the value of the State field of the oEvent to the main program through the Public variable Statex1
End Sub
Sub print_listener_disposing
End Sub
I have a textedit component and a button component. The button component will add the textedit component text value to a list if that value is greater than 0. On the textedit component I can as many decimal places as I want, but I'd like to validate two decimal places. Like If I put 00.0032 in the textedit component the validation will take that as 0. Is there a function that will allow me to do this or do I have to do this by my own code.
This is my code
if (Trim(textEdit.Text) <> '') and (StrToCurr(Trim(textEdit.Text)) <> 0) then
begin
code to add the value
end;
Reading your question two possible solutions come to my mind:
You could convert to float multiply by 100 (to shift by two decimals) and round using floor:
(Floor(StrToFloat(Trim(textEdit.Text)) * 100) <> 0)
This performs a conversion to floating point which might be slow.
An other solution could be to use string functions:
(StrToCurr(Copy(textEdit.Text, 1, Pos('.', textEdit.Text) + 2)) <> 0)
This copies the input string from beginning to two digits after the decimal separator '.'.
Don't worry if your string is shorter (for example '0.1') you won't get an error.
Which solution is ultimately fast would have to be benchmarked.
Also have in mind, that not in every region a '.' is the decimal separator.
In most of Europe for example decimal separator is ',' and thousands separator is '.'.
Find out about TFormatSettings.
PS: You don't need to Trim before using StrToCurr because it does a trim internally.
I have an SPSS variable containing lines like:
|2|3|4|5|6|7|8|10|11|12|13|14|15|16|18|20|21|22|23|24|25|26|27|28|29|
Every line starts with pipe, and ends with one. I need to refactor it into boolean variables as the following:
var var1 var2 var3 var4 var5
|2|4|5| 0 1 0 1 1
I have tried to do it with a loop like:
loop # = 1 to 72.
compute var# = SUBSTR(var,2#,1).
end loop.
exe.
My code won't work with 2 or more digits long numbers and also it won't place the values into their respective variables, so I've tried nest the char.substr(var,char.rindex(var,'|') + 1) into another loop with no luck because it still won't allow me to recognize the variable number.
How can I do it?
This looks like a nice job for the DO REPEAT command. However the type conversion is somewhat tricky:
DO REPEAT var#i=var1 TO var72
/i=1 TO 72.
COMPUTE var#i = CHAR.INDEX(var,CONCAT("|",LTRIM(STRING(i,F2.0)),"|"))>0).
END REPEAT.
Explanation: Let's go from the inside to the outside:
STRING(value,F2.0) converts the numeric values into a string of two digits (with a leading white space where the number consist of just one digit), e.g. 2 -> " 2".
LTRIM() removes the leading whitespaces, e.g. " 2" -> "2".
CONCAT() concatenates strings. In the above code it adds the "|" before and after the number, e.g. "2" -> "|2|"
CHAR.INDEX(stringvar,searchstring) returns the position at which the searchstring was found. It returns 0 if the searchstring wasn't found.
CHAR.INDEX(stringvar,searchstring)>0 returns a boolean value indicating if the searchstring was found or not.
It's easier to do the manipulations in Python than native SPSS syntax.
You can use SPSSINC TRANS extension for this purpose.
/* Example data*/.
data list free / TextStr (a99).
begin data.
"|2|3|4|5|6|7|8|10|11|12|13|14|15|16|18|20|21|22|23|24|25|26|27|28|29|"
end data.
/* defining function to achieve task */.
begin program.
def runTask(x):
numbers=map(int,filter(None,[i.strip() for i in x.lstrip('|').split("|")]))
answer=[1 if i in numbers else 0 for i in xrange(1,max(numbers)+1)]
return answer
end program.
/* Run job*/.
spssinc trans result = V1 to V30 type=0 /formula "runTask(TextStr)".
exe.
I have a TDateTime value (that I get as result from EndOfTheMonth(date)) to a variant type. The result is wrongly rounded. Let's have a look at example:
data := EndOfTheMonth(date);
V := data;
ShowMessage(DateTimeToStr(data) + ' vs ' + VarToStr(V));
// output is
// data = 2012-01-31 23:59:59
// v = 2012-02-01 // why next day?
Is it designed behaviour?
How to work around this?
ShowMessage(DateTimeToStr(data) + ' vs ' + DateTimeToStr(VarToDateTime(V)));
Update: I would guess the problem is that the last millisecond of the month is very close to 0:00:00 the next day, that is, the TDateTime value (which is basically a double) is very close to an integer (e.g. 41029.9999999884 is very close to 41029) and so the VarToStr function assumes the decimals to be numerical fuzz.