VBA Run String as Code - vba

I want to read strings of code from a database. A string should include pieces of text and one/two variables which are set later in the project. The result should look like this:
"Greetings, Tom."
Usually I would do something like this:
Sub Show()
Dim strName as String
strName = "Tom"
Debug.Print "Greetings, " & strName & "."
...
But in this case the part
"Greetings, " & strName & "."
is on my database. During runtime I set the value of strName to multiple names (eg in one case to "Tom" and in another case to "Marco")
How is it possible to let VBA know that strName is a variable and not a string to be shown? In the end my call should look like this:
strDbText = <String from Database>
strName = "Tom"
Debug.Print strDbText '--> Greetings, Tom.
Can anyone help me out one more time?
Thanks a lot!
edit:
This code will not be an executable. So there is no need to go for the VBIDE-Objects to create a new module and execute inserted code. It is a string which will be written in a Word Document.
Solution:
String Substitution with the Replace() function

I would assign strName first and replace it with the string in the Database like this...
strName = "Tom"
strDbText = <String from Database>
strDbText = Replace(strDbText, "strName", strName) 'This distinguishes the string from the variable
Debug.Print strDbText '--> Greetings, Tom.
However, I would suggest using another variable in your database in place of strName because it may become confusing to look at.

Absolutely agreeing #ShanayL answer and strongly recommending its usage, I couldn't avoid pointing an unsafe alternative to solve your question, using Eval. Eval is potentially dangerous, creating a code injection vulnerability in your application!!!
strDbText = """Greetings, "" & strName"
strName = "Tom"
Debug.Print Eval(strDbText) 'Greetings, Tom
Notice: Eval is potentially dangerous and its usage is strongly disencouraged!

Related

Generate a SSRS report in default browser from VB.NET

I have a VB.NET solution that stores data to a SQL database. I have written the first of several SSRS reports. Now I want to generate the reports from my VB.NET solution.
I have a subroutine that will generate the report,
Public Shared Sub GenerateReport(ByVal RptName As String, ByVal ParamArray Params() As Object)
Dim strPath As String = sqlSSRS + Replace(RptName, " ", "%20")
Dim _class As cParameters
'strPath += "&rc:Parameters=false&rs:Command=Render"
'strPath += "&rs:Command=Render"
For i As Integer = 0 To UBound(Params)
_class = DirectCast(Params(i), cParameters)
strPath += "&" & _class.ParamName & "=" & _class.Value
Next
System.Diagnostics.Process.Start(strPath)
End Sub
If I generate a path with no parameters the report will open in the default browser. So this works...
http://sqlServerName:80/Reports/report/ToolCrib/Toolbox%20by%20Installer
But neither this ...
http://sqlServerName:80/Reports/report/ToolCrib/Toolbox%20by%20Installer&#UserID=7&#ProjectID=20026&#ToolboxID=10&#ToolStatus=2
or this
http://sqlServerName:80/Reports/report/ToolCrib/Toolbox%20by%20Installer&UserID=7&ProjectID=20026&ToolboxID=10&ToolStatus=2
does.
I obviously have an issue passing parameters. In one case I don't need them but in other cases I want to provide them, which is why I wrote the GenerateReport routine with the optional Parameter array. Here is the error message I get which I know from past experience is sort of a catch all when MS doesn't "know" how else to classify an SSRS error.
The path of the item '/ToolCrib/Toolbox by Installer&UserID=7&ProjectID=20026&ToolboxID=10&ToolStatus=2' is not valid. The full path must be less than 260 characters long; other restrictions apply. If the report server is in native mode, the path must start with slash. (rsInvalidItemPath)
Any help will be greatly appreciated.
You path needs to use reportserver? instead of Reports/report when using parameters.
Try
http://sqlServerName:80/reportserver?/ToolCrib/Toolbox%20by%20Installer&UserID=7&ProjectID=20026&ToolboxID=10&ToolStatus=2
You could add a REPLACE:
strPath = Replace(strPath, "/Reports/report/", "/reportserver?/")
For more reading, you can check out
MS Docs url-access-parameter-reference

Parse enum values by name in VBA

I want to write some VBA code that should parse MSForms-constant names (given as a string, like "fmTextAlignLeft") into their actual value. Since there is no native way to do so I was considering to put the name of the constant into a powershell code that will then be executed and return the result.
Private Sub ParseEnumByName(EnumConst As String)
Dim WScript As New WshShell
Dim PSCode As String
Dim Result
PSCode = "(some code)" & EnumConst & "(more code with exit $Value statement)"
Result = WScript.Run("Powershell -command """ & PSCode & """", 0, True)
ParseEnumByName = Result
End Sub
This should be feasible by iterating through all enums in the MSForms library and get the values out of them with something like
[System.Enum]::GetNames( [System.Windows.Forms.FormBorderStyle] ) or maybe something like explained here: How to convert a string to a enum?
The problem is that the System.Windows.Forms library contains totally different enums and typenames than the MSForms library available in VBA.
I tried to Add-Type -Path "C:\Windows\SysWOW64\FM20.DLL" where the MSForms library is stored but it returns an error saying the file or assembly or some related file could not be found.
How may I get a reference to MSForms in Powershell?
Edit: I have actually found a demi-native way in VBA (Excel VBA only) to solve this issue without passing values to external script hosts. Please see below.
Here's the function I figured out. So far it seems to work with all pre-defined enums and constants and also self defined enums in Excel. The function must be placed in a module!
Static Function ParseValue(StringValue) As Variant
Dim ParseValueBuffer As Variant
If IsEmpty(ParseValueBuffer) Then
ParseValueBuffer = 1
Application.Run ("'ParseValue " & StringValue & "'")
ParseValue = ParseValueBuffer
ParseValueBuffer = Empty
Else
ParseValueBuffer = StringValue
End If
End Function
Sub TestMe()
MsgBox "First line" & ParseValue("vbcrlf") & "Second line"
MsgBox ParseValue("fmTextAlignCenter") 'Should return "2" (if MSForms is referenced)
MsgBox ParseValue("rgbblue") 'Should return 16711680
End Sub

How to add quotation marks to 2 strings and variable in the middle

I'm trying to add quotations to a piece of string that is broken in 2 pieces with a variable in the middle.
I have tried many, many ways...many ways and failed.
Example:
Dim path as String = "C:\Users\" & CurrentUser & "\folder\path to something\"
I need the whole result to be in quotations to pass it to a command that requires the path with spaces in quotations.
"C:\Users\Nemo\Folder\Path to something\"
Any help is appreciated.
You should just be able to use "" inside the string assignment that you have. So with your example it would look like this:
Dim path As String = """C:\Users\" & CurrentUser & "\folder\path to something\"""
IMHO it is a good idea to use CHR(34) instead of actual quotes when concatenating strings. Your code should look like this:
Dim current user as string="Nemo"
Dim path as String = CHR(34) & "C:\Users\" & CurrentUser & "\folder\path to something\" & CHR(34)
The result will be:
"C:\Users\Nemo\folder\path to something\"

Custom function in Excel for cell hyperlink creation

For example, if i have a complex functions like this one: =IFERROR(CELL("address",INDEX(D:D,MATCH(A2;D3:D$750;0)+ROW(A2);1;1));"") i want to convert it into hyperlink which points to cell returned by that formula. And yeah, i know that it could be done by wrapping it with =HYPERLINK("[file_name.xlsm]" & %formula%) BUT, first of all, it looks very ugly and uncomfortable to read in the big sparse data, and second - it is very inconvenient to copy such data-blocks between Excel instances (and then replace filename).
So i wonder - is it possible to convert such output into cell-link for current file and sheet with readable text like "D156" in place of "[long_file_name.xlsm]$D$156"?
P.S. obviously i can make a custom function which returns current filename and put same formula into second argument of HYPERLINK func, but obviously it will be counter-effective, especially when i have huge chunks of data. So i want to wrap all this into 1 function...
P.P.S. Don't sure if this will be appropriate (it's kinda offtopic for this question), but it will be fine if the same functionality could be done with macro instead of custom function. So the macro should find all the duplicates inside of currently selected range and make hyperlinks (in cell with same offset on different sheet with offset +1, the next sheet after currently active) to next occurrence of every duplicate. The rest i can manage by myself.
UPD1:
Getting filename is not a problem, as i said in P.S., i can write a function like this:
Function GetCurFilename()
GetCurFilename= "[" & ActiveWorkbook.Name & "]"
End Function
but i still need somehow to send part of the first HYPERLINK's argument as second one!
UPD2:
I guess it should be done like this:
Function MakeLinkArgs(cAdrs) As SomeType_interpreted_as_2_arguments
If (cAdrs = "") Then
MakeLinkArgs(1) = ""
MakeLinkArgs(2) = ""
Else
MakeLinkArgs(1) = "[" & ActiveWorkbook.Name & "]" & cAdrs
MakeLinkArgs(2) = Replace(cAdrs, "$", "")
End If
End Function
So this func could be used like this: =HYPERLINK( MakeLinkArgs( IFERROR(CELL("address",INDEX(D:D,MATCH(A2;D3:D$750;0)+ROW(A2);1;1));"") ) )
But still no luck finding type which could be interpreted as 2 arguments (don't sure if such exists at all)...
Not totally sure what you are asking, but I think that =CELL("filename") will help you. This returns both the filename and the sheet. Just extract the sheet name and file name from what this returns. Also portable for cut/paste to other workbooks/worksheets.
Well, i didn't found a way to send multiple arguments with single result from other function, but i found a side way to do what i want. It looks like a dirty hack to me, but i don't sure, maybe it's the way to do things in Excel VBA...
So first it's needed to add a public variable at the top of the Module:
Public sBuff As String
Next, these 2 functions should be added after public var declaration:
Function MakeCLink(cAdrs)
If (cAdrs = "") Then
MakeCLink = ""
sBuff = ""
Else
MakeCLink = "[" & ActiveWorkbook.Name & "]" & cAdrs
sBuff = Replace(cAdrs, "$", "")
End If
End Function
Function sBuf() As String
sBuf = "" & sBuff
End Function
And after compilation it could be used in formulas as such: =HYPERLINK( MakeCLink(IFERROR(CELL("address",INDEX(D:D,MATCH(A2,D3:D$750,0)+ROW(A2),1,1)),"")), sBuf() )
Yes, it's ugly, but works as magic for me =)

Concatenating a complex string in VB. NET

I am using START-PROCESS to call MSTEST with multiple arguments that define the container and test settings, however I think it's choking on the way I'm concatenating this. Should I use some other method of constructing this string before putting it into START-PROCESS?
Dim rwSettings As String = "\\PerfvsCtlr2\LoadtestSettings\PerfVSCtlr2forRemote.testsettings"
Dim rwContainer As String = "\\PerfvsCtlr2\LoadTest\LoadTestDefs\Heifer_Interactive_Peak_Workload.loadtest"
Dim rwResults As String = Workload.txtRwResults.Text
System.Diagnostics.Process.Start(Environment.GetEnvironmentVariable("VS110COMNTOOLS") & "..\Ide\MSTEST.EXE", "/Testsettings:""" & rwSettings & "" & " /Testcontainer:""" & rwContainer & "" & " /Resultsfile:""" & rwResults & "")
The problem is unknown currently, because process.start opens and closes the window far too quickly for me to catch any sort of error message. So my question is two-fold:
Does the above concatenation look correct? Is there a way I can get more information on either the final execution string Process.Start is putting together or the error message it's returning?
You can use Path.Combine to build paths and String.Format to build the arguments for Process.Start:
Dim rwSettings As String = "\\PerfvsCtlr2\LoadtestSettings\PerfVSCtlr2forRemote.testsettings"
Dim rwContainer As String = "\\PerfvsCtlr2\LoadTest\LoadTestDefs\Heifer_Interactive_Peak_Workload.loadtest"
Dim rwResults As String = "Workload.txtRwResults.Text"
Dim fileName = System.IO.Path.Combine(Environment.GetEnvironmentVariable("VS110COMNTOOLS"), "Ide\MSTEST.EXE")
Dim args = String.Format("/Testsettings:{0} /Testcontainer:{1} /Resultsfile:{2}", rwSettings, rwContainer, rwResults)
System.Diagnostics.Process.Start(fileName, args)
However, i must admit thar i'm not sure if this yields the desired result. It might give you an idea anyway.
I suspect that your problem is that you are not closing your quotation marks, for instance:
" /Testcontainer:""" & rwContainer & ""
Should be:
" /Testcontainer:""" & rwContainer & """"
Notice that the double-quotation mark at the end needs to be a quadruple quotation mark. Simply saying "" means an empty string.
Should you use something else? Probably. It would be more readable and efficient if you used StringBuilder or String.Format, but even so, you'll still have to fix the closing quotes issue.