excel vba variables in functions - excel

i have an automation that performs a few different actions which definitely requires a login, so i coded all the actions in modules and have 1 main login script that will call upon the different modules base on the codes that was sent by the buttons.
Buttons
Sub Button_Click()
Call LoginPhase(F1Function1)
DoEvents
End Sub
Function
Public Function LoginPhase(FunctionKey)
....
If FunctionKey = "F1Function1" Then
Call Scrape(intX)
ElseIf FunctionKey = "F2Function2" Then
Call BuyBuyBuy(intX, Epin)
Call Scrape(intX)
ElseIf FunctionKey = "F3Function3" Then
Call BuyBuyBuy2(intX, Epin)
Call Scrape(intX)
Else
MsgBox "Not Relevant."
End If
....
End Function
But it seem that it never recognize any of the FunctionKey value and goes straight to MsgBox "Not Relevant". Anyone have any idea how i can solve this ?

Related

Cannot change color of a shape in Excel

VBA noob here.
I am developing a workbook which makes use of an external dll from my client.
In a sheet I have a button that, when pressed, starts a routine which makes a shape orange, then calls the API and finally makes the shape black.
Misteriously, it works only 'few times'.
The following code resides in a sub within a module:
Dim shapeToFlash As String
shapeToFlash = "SHAPE " & sheetName
Worksheets("GTE HOME").Shapes(shapeToFlash).Fill.ForeColor.SchemeColor = 53
Worksheets("HOME").Shapes(shapeToFlash).Fill.ForeColor.SchemeColor = 53
// API CALL (kind of long operation ~ 3/4 seconds)
Worksheets("GTE HOME").Shapes(shapeToFlash).Fill.ForeColor.SchemeColor = 0
Worksheets("HOME").Shapes(shapeToFlash).Fill.ForeColor.SchemeColor = 0
I cannot share details about the API. I simply declare with the traditional sintax:
#If Win64 Then
Private Declare PtrSafe Function IMB_set_value _
Lib "path/API.dll" () As Long
#Else
Private Declare Function IMB_set_value _
Lib "path/API.dll" () As Long
and works perfectly.
The problem is that the first SchemeColor (to 53) does not work meaning that the API is called and the second SchemeColor too (the shape turns black). Just to test, I tried to comment the second SchemeColor (to 0) and I noticed that in this case the shape turns orange AFTER the API is called! That suggested me Excel create a sort of priority queue of the commands to be executed and that the API call is performed before the first SchemeColor: that clearly messes with my flow. Is there a way to force Excel to execute immediately an operation? Is there another reason for the fail?
P.S.: I have executed the first SchemeColor lines of code separately and works nicely so I suppose the code is correct.
P.P.S.: I have also tried using RGB instead of SchemeColor, with the same result.
Try this
Sub InitiateLongRunningOperation()
Dim Argument as String
HighlightShape
Argument = "Argument Value"
Application.OnTime Now, "'LongRunningOperation """ & Argument & """'"
End Sub
Sub HighlightShape()
Worksheets(1).Shapes(1).Fill.ForeColor.SchemeColor = 53
End Sub
Sub LongRunningOperation(AnArgument As String)
Debug.Print AnArgument
' Replace the line below with your API call
Application.Wait Now + TimeValue("0:00:03")
Application.OnTime Now, "ResetShape"
End Sub
Sub ResetShape()
Worksheets(1).Shapes(1).Fill.ForeColor.SchemeColor = 0
End Sub
It works with Application.OnTime to start the chain of events without waiting for all of it to end before updating.
I have changed some of your code to make it easier to reproduce, but I think you will be able to follow it quite easy.

Excel VBA - on Multi Page Change but only once

I have a flexgrid within a Multipage under Main_Window.MultiPage2.Value = 2 this flexgrid has 8000 rows and I don't want those to load unless this page is actually clicked on. The code I have does just that, but the problem is is that it loads every single time and not just once. Is there a way to make it load on the first change, and then that's it?
Private Sub MultiPage2_Change()
If Main_Window.MultiPage2.Value = 2 Then
Call form_segment_carrier_auto
End If
End Sub
in form_segment_carrier_auto is a module that populates the flexgrid.
If I understand you correctly, you could declare a Public Boolean variable, for example:
Public ChangedOnce As Boolean
This should be in some standard code module.
Then change your event handler to:
Private Sub MultiPage2_Change()
If ChangedOnce Then Exit Sub
ChangedOnce = True
If Main_Window.MultiPage2.Value = 2 Then
Call form_segment_carrier_auto
End If
End Sub
The event handler will still be called on multiple occasions if the event occurs on multiple occasions, but only the first call will do anything.

Macro not working right when called through a button

Using Excel 07
Below is the code I currently have working. However when I assign it to a code the section where it clear contents does not run but everything else does. If I just F8 through it clears the contents no problem at all. I am not sure why this is and was hoping you could help.
Sub Save_Session()
Call UnProtectAll
If Worksheets("Drawing").Range("A2").Value = Worksheets("Drawing").Range("I2").Value Then
i = (Worksheets("Drawing").Range("B2").Value * 25) - 24
Worksheets("Drawing").UsedRange.Copy Destination:=Worksheets("Sessions").Range("A" & i)
Worksheets("Drawing").Range("B2").Value = Worksheets("Drawing").Range("B2").Value + 1
With Sheets("Drawing")
Range("A2").ClearContents
Range("C2:C20").ClearContents
Range("E2:H20").ClearContents
End With
Else
MsgBox "You do not have all the winners yet!!!"
End If
Sheets("Drawing").Select
Call ProtectAll
End Sub
It's probably working when you step through coincidentally because you happen to be on the sheet "Drawing" when running the macro.
To access properties or parameters of an object, you need to use the "." Since you are already declaring what you are trying to access with the WITH statement.
Here is an article from MSDN explaining how the WITH...End statement works In VBA.
With Sheets("Drawing")
.Range("A2").ClearContents
.Range("C2:C20").ClearContents
.Range("E2:H20").ClearContents
End With

EXCEL VBA: calling an event with onclick property of a button which is being created on the fly

I am creating a excel VBA userform which requires many buttons to be created on the fly (ie as the requirement may be, runtime). I want to assign a subroutine to these buttons so that when they are clicked a subroutine should execute.
this is what I want to do
Set obj4 = usrform.Controls.Add("forms.commandbutton.1")
obj4.Height = 17
obj4.Left = 450
obj4.Top = 75
obj4.Font.Size = 11
obj4.Name = "compare" & (j - i) 'j and i are some variables in the code
obj4.Caption = "Compare!"
obj4.onclick = abcd
public sub abcd()
'some code here
end sub
but this code is not running. I read somewhere that here I cannot call a subroutine but a function. My problem is that I want a subroutine only as I dont intend to get something in return from it. But still for trial purpose I made abcd() a function in the above code and then my code was running but unsuccessfully as it was executing the function abcd without the need of button getting pressed.
Can anyone help me with this? I have searched a lot for this on internet in various forums.
Don't get hung up on subroutine v. function: if you don't set the return value of a function, it's the same as a subroutine.
When you set the onClick property, you give it the name of the function as a string obj4.onclick = "abcd" otherwise it will execute the function and save the return value.

VB6 DoEvents not Working as Desired

I am working with a proprietary VB6 COM library. The library has some functions which fire and I get the results once complete through Events.
Container Class:
Private WithEvents myObj As proprietaryObj
Public status as Integer
Set myObj = new proprietaryObj
status = 1
Call myObj.DoIt1()
...
' Call back event function
Private Sub myObj_Done(ByVal Code As Long)
...
MsgBox "Finished"
status = 2
End Sub
So everything works well (verified). What I want to do is encapsulate the above code + more in a class, so that I wrap multiple functions which need to stack, or get executed consecutively after a successful callback report.
So I went ahead and did this:
Call myObj.DoIt1()
Do
If myObj.Status = 2 Then Exit Do
If myObj.Status = -1 Then Exit Do 'Error
DoEvents
Loop
call myObj.DoIt2()
I get the "Finished" dialog box, but DoIt2 never fires. In fact, if I pause my code while running debug after I see the "Finished" message, the code is currently executing the DoEvents, and the myObj.Status = 1 as if it were never touched.
It almost seems as if a different instance of the object was created for a separate thread? How do I safely and correctly wait for the event callback to fire before continuing execution with the next DoIt2() ?
You need to use your local status variable, because that is what you are setting to 2:
Call myObj.DoIt1()
Do
If status = 2 Then Exit Do
If status = -1 Then Exit Do 'Error
DoEvents
Loop
call myObj.DoIt2()
Else you could also try to set status = 2 before the call to MsgBox "Finished".

Resources