In access using VB my code is:
Private Sub Form_Timer()
Static OldcontrolName As String
Static OldFormName As String
Static ExpiredTime
Dim ActivecontrolName As String
Dim ActiveFormName As String
Dim ExpiredMinutes
On Error Resume Next
ActivecontrolName = Screen.ActiveControl.Name
ActiveFormName = Screen.ActiveForm.Name
If (OldcontrolName = "") Or (OldFormName = "") Or (ActiveFormName <> OldFormName) Or
(ActivecontrolName <> OldcontrolName) Then
OldcontrolName = ActivecontrolName
OldFormName = ActiveFormName
ExpiredTime = 0
Else
ExpiredTime = ExpiredTime + Me.TimerInterval
End If
ExpiredMinutes = (ExpiredTime / 1000)
If ExpiredMinutes >= 600 Then
ExpiredTime = 0
Application.Quit acQuitSaveAll
End If
End Sub
This seems to work great. I can put the time down to 5 seconds to test and it's perfect but as soon as I turn off the navigation pane and then try to close access it throws the error:
Run-time error '5':
Invalid procedure call or argument
Related
I have been trying to develop a console application that will open an existing Excel workbook and write data into the sheet. The data it is gathering is coming from another application called NX, a CAD program. I wrote the console app in VB.NET, using Framework 4.5 and Office 2010. The code works as it should, except for the event based code. I included some functionality that should fire off when a selection change event occurs. I have spent weeks doing research and trying to discover why my event based code will not fire off. The only conclusion I seem to be coming is that the console app is immediately getting closed/completed and not giving "enough time" for the event handler to get kicked.
Here is my code:
Option Strict Off
Option Infer Off
Imports System.IO
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Text
Imports System.Diagnostics
Imports System.Collections
Imports System.Collections.Generic
Imports NXOpen
Imports NXOpen.Assemblies
Imports NXOpen.Utilities
Imports NXOpen.UF
Imports Microsoft.Office.Interop ' import Excel Interop Namespace
Imports System.Runtime.InteropServices.Marshal
Imports Microsoft.Office.Interop.Excel
Imports System.Windows.Forms
Module remoting_client_test
Public theSession As Session = DirectCast(Activator.GetObject(GetType(Session), "http://localhost:4567/NXOpenSession"), Session)
Public ufs As UFSession = DirectCast(Activator.GetObject(GetType(UFSession), "http://localhost:4567/UFSession"), UFSession)
Public workPart As Part = theSession.Parts.Work
Public displayPart As Part = theSession.Parts.Display
Public TagIdentifier As Long
Public row As Long = 3
Sub Main()
Dim myForm As New Form1
'need to initialize value of excel object variables
myForm.OpenWorkBook("C:\Path File")
myForm.ProcessNXData()
End Sub
Public Sub DoLog(s As [String])
Session.GetSession().LogFile.WriteLine(s)
Console.WriteLine(s)
End Sub
Sub Echo(ByVal output As String)
theSession.ListingWindow.Open()
theSession.ListingWindow.WriteLine(output)
theSession.LogFile.WriteLine(output)
End Sub
Public Function GetUnloadOption(ByVal dummy As String) As Integer
Return Session.LibraryUnloadOption.Immediately
End Function
End Module
Public Class Form1
Private WithEvents excel As Excel.Application
Private WithEvents workbook As Excel.Workbook
Private WithEvents myWorksheet As Excel.Worksheet
Public Sub OpenWorkBook(path As String)
If excel Is Nothing Then
excel = New Excel.Application
excel.Visible = True ' user is responsible for closing Excel
excel.UserControl = True
excel.EnableEvents = True
End If
If workbook IsNot Nothing Then
FreeCOM(workbook)
End If
Dim workbooks As Excel.Workbooks = excel.Workbooks
workbook = workbooks.Open(path)
FreeCOM(workbooks)
If myWorksheet IsNot Nothing Then
FreeCOM(myWorksheet)
End If
Dim Worksheets As Excel.Sheets = workbook.Worksheets
myWorksheet = CType(Worksheets.Item(1), Microsoft.Office.Interop.Excel.Worksheet) ' 1 based indexing
Worksheets("NX Data").Activate()
myWorksheet = Worksheets("NX Data")
End Sub
Public Shared Sub FreeCOM(ByVal COMObj As Object, Optional ByVal GCCollect As Boolean = False)
Try
If COMObj IsNot Nothing Then
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(COMObj)
End If
Finally
COMObj = Nothing
If GCCollect Then
GC.Collect()
GC.WaitForPendingFinalizers()
End If
End Try
End Sub
Public Sub ProcessNXData()
' This assumes the assembly is loaded.
Dim dp As Part = theSession.Parts.Display
Dim row As Long = 3
theSession.EnableRedo(False)
Dim nextBody As NXOpen.Tag = NXOpen.Tag.Null
Do
Dim t As Integer, st As Integer
Dim isOcc As Boolean = False
Dim theProtoTag As NXOpen.Tag = NXOpen.Tag.Null
Dim owningPart As NXOpen.Tag = nextBody
Dim partName As String = ""
ufs.Obj.CycleTypedObjsInPart(dp.Tag, UFConstants.UF_solid_type, nextBody)
If nextBody.Equals(NXOpen.Tag.Null) Then
Exit Do
End If
ufs.Obj.AskTypeAndSubtype(nextBody, t, st)
If st <> UFConstants.UF_solid_body_subtype Then
Continue Do
End If
isOcc = ufs.Assem.IsOccurrence(nextBody)
If isOcc.Equals(True) Then
'Echo("Found occurrence body: " & nextBody.ToString())
theProtoTag = ufs.Assem.AskPrototypeOfOcc(nextBody)
ufs.Obj.AskOwningPart(theProtoTag, owningPart)
ufs.Part.AskPartName(owningPart, partName)
Echo("Owning Part: " & partName)
End If
Dim theNXOM As NXObjectManager = theSession.GetObjectManager
Dim theObj As NXObject = theNXOM.GetTaggedObject(nextBody)
Dim theBody As Body = CType(theObj, Body)
Dim myMeasure As MeasureManager = theSession.Parts.Display.MeasureManager()
Dim massUnits(4) As Unit
massUnits(0) = theSession.Parts.Display.UnitCollection.GetBase("Area")
massUnits(1) = theSession.Parts.Display.UnitCollection.GetBase("Volume")
massUnits(2) = theSession.Parts.Display.UnitCollection.GetBase("Mass")
massUnits(3) = theSession.Parts.Display.UnitCollection.GetBase("Length")
Dim singleBodyArray() As Body = {theBody}
Dim mb As MeasureBodies = myMeasure.NewMassProperties(massUnits, 1, singleBodyArray)
mb.InformationUnit = MeasureBodies.AnalysisUnit.PoundFoot
Dim centroidalPoint As Point3d = mb.Centroid()
Echo("Centroid: " & centroidalPoint.X & " " & centroidalPoint.Y & " " & centroidalPoint.Z)
Echo(" ")
'get parent tag
Dim parentTag As Tag
ufs.Assem.AskParentComponent(theBody.Tag, parentTag)
Dim bodyComp As Component = theSession.GetObjectManager.GetTaggedObject(parentTag)
'get root name
Dim c As ComponentAssembly = workPart.ComponentAssembly
excel.Cells(2, 2) = theBody.OwningPart.Leaf
excel.Cells(2, 3).value = c.RootComponent.GetStringAttribute("DB_PART_NAME")
'find attribute data
If bodyComp.HasUserAttribute("DB_PART_NAME", NXObject.AttributeType.String, -1) = True Then
excel.Cells(row, 3) = bodyComp.GetStringAttribute("DB_PART_NAME")
End If
If bodyComp.HasUserAttribute("MF Material", NXObject.AttributeType.String, -1) = True Then
excel.Cells(row, 7) = bodyComp.GetStringAttribute("MF Material")
End If
If bodyComp.HasUserAttribute("MF NN", NXObject.AttributeType.String, -1) = True Then
excel.Cells(row, 9) = bodyComp.GetStringAttribute("MF NN")
End If
If bodyComp.HasUserAttribute("MF Modifier", NXObject.AttributeType.String, -1) = True Then
excel.Cells(row, 8) = bodyComp.GetStringAttribute("MF Modifier")
End If
If bodyComp.HasUserAttribute("MF Type", NXObject.AttributeType.String, -1) = True Then
excel.Cells(row, 10) = bodyComp.GetStringAttribute("MF Type")
End If
'bounding box
Dim bodyLengths(2) As Double
bodyLengths = GetBoundingBox(theBody)
'Measures Min/Max of all model parts in assembly
Dim bbox(5) As Double
Dim tagList(0) As NXOpen.Tag
ufs.Modl.AskBoundingBox(theBody.Tag, bbox)
'write data to cells
excel.Cells(row, 2).value = bodyComp.Parent.Prototype.OwningPart.Leaf
excel.Cells(row, 4).value = bodyComp.Prototype.OwningPart.Leaf
excel.Cells(row, 11).value = mb.Volume.ToString
excel.Cells(row, 14).value = centroidalPoint.Z
excel.Cells(row, 16).value = centroidalPoint.X
excel.Cells(row, 18).value = centroidalPoint.Y
excel.Cells(row, 21) = (bbox(0) / 12) 'LCG
excel.Cells(row, 22) = (bbox(3) / 12)
excel.Cells(row, 23) = (bbox(2) / 12) 'VCG
excel.Cells(row, 24) = (bbox(5) / 12)
excel.Cells(row, 25) = (bbox(1) / 12) 'TCG
excel.Cells(row, 26) = (bbox(4) / 12)
excel.Cells(row, 50).value = nextBody.ToString
row = row + 1
Loop Until nextBody.Equals(NXOpen.Tag.Null)
End Sub
Private Function GetBoundingBox(ByVal solidBody As NXOpen.Body) As Double()
'AskBoundingBox returns min and max coordinates
'this function will simply return the box lengths (x, y, z)
Dim bboxCoordinates(5) As Double
Dim bboxLengths(2) As Double
Try
'get solid body bounding box extents
ufs.Modl.AskBoundingBox(solidBody.Tag, bboxCoordinates)
bboxLengths(0) = bboxCoordinates(3) - bboxCoordinates(0)
bboxLengths(1) = bboxCoordinates(4) - bboxCoordinates(1)
bboxLengths(2) = bboxCoordinates(5) - bboxCoordinates(2)
Return bboxLengths
Catch ex As NXException
MsgBox(ex.GetType.ToString & " : " & ex.Message, MsgBoxStyle.OkOnly + MsgBoxStyle.Exclamation, "Solid Body Bounds Error!")
bboxLengths(0) = 0
bboxLengths(1) = 0
bboxLengths(2) = 0
Return bboxLengths
End Try
End Function
Sub Echo(ByVal output As String)
theSession.ListingWindow.Open()
theSession.ListingWindow.WriteLine(output)
theSession.LogFile.WriteLine(output)
End Sub
Public Function GetUnloadOption(ByVal arg As String) As Integer
Return Session.LibraryUnloadOption.Immediately
End Function
Public Sub myWorksheet_SelectionChange(ByVal Target As Excel.Range) Handles myWorksheet.SelectionChange
MsgBox("its firing")
Dim theSession As Session = DirectCast(Activator.GetObject(GetType(Session), "http://localhost:4567/NXOpenSession"), Session)
Dim ufs As UFSession = DirectCast(Activator.GetObject(GetType(UFSession), "http://localhost:4567/UFSession"), UFSession)
Dim workPart As Part = theSession.Parts.Work
Dim dp As Part = theSession.Parts.Display
'Dim theCompName As String
Dim theCompTag As NXOpen.Tag = NXOpen.Tag.Null
Dim RowNum As Long
RowNum = Target.Row
TagIdentifier = excel.Cells(RowNum, 50).value()
ufs.Disp.SetHighlight(TagIdentifier, 1)
ReleaseComObject(Target)
End Sub
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
If myWorksheet IsNot Nothing Then
FreeCOM(myWorksheet)
End If
If workbook IsNot Nothing Then
FreeCOM(myWorksheet)
End If
If excel IsNot Nothing Then
FreeCOM(excel, True)
End If
End Sub
End Class
Can somebody please tell me what they think the issue is?
I am developing an application in visual basic 2010, that finds the memory usage of a particular process. I came across this code:
Option Explicit
Private Sub Command1_Click()
Debug.Print GetProcessMemory("vb6.exe")
End Sub
Private Function GetProcessMemory(ByVal app_name As String) As String
Dim Process As Object
Dim dMemory As Double
For Each Process In GetObject("winmgmts:").ExecQuery("Select WorkingSetSize from Win32_Process Where Name = '" & app_name & "'")
dMemory = Process.WorkingSetSize
Next
If dMemory > 0 Then
GetProcessMemory = ResizeKb(dMemory)
Else
GetProcessMemory = "0 Bytes"
End If
End Function
Private Function ResizeKb(ByVal b As Double) As String
Dim bSize(8) As String, i As Integer
bSize(0) = "Bytes"
bSize(1) = "KB" 'Kilobytes
bSize(2) = "MB" 'Megabytes
bSize(3) = "GB" 'Gigabytes
bSize(4) = "TB" 'Terabytes
bSize(5) = "PB" 'Petabytes
bSize(6) = "EB" 'Exabytes
bSize(7) = "ZB" 'Zettabytes
bSize(8) = "YB" 'Yottabytes
For i = UBound(bSize) To 0 Step -1
If b >= (1024 ^ i) Then
ResizeKb = ThreeNonZeroDigits(b / (1024 ^ _
i)) & " " & bSize(i)
Exit For
End If
Next
End Function
Private Function ThreeNonZeroDigits(ByVal value As Double) As Double
If value >= 100 Then
ThreeNonZeroDigits = FormatNumber(value)
ElseIf value >= 10 Then
ThreeNonZeroDigits = FormatNumber(value, 1)
Else
ThreeNonZeroDigits = FormatNumber(value, 2)
End If
End Function
but this does not work in vb2010. It returns 0bytes. Please help. Alternative techniques are also appreciated.
Hi to give some context the code below is from an Access database that was left to me from the previous employee, Unfortunately I am not very good at VBA.
I would appreciate any help in identifying its purpose.
Private Sub Command83_Click()
On Error GoTo Err_Command83_Click
Dim stDialStr As String
Dim PrevCtl As Control
Const ERR_OBJNOTEXIST = 2467
Const ERR_OBJNOTSET = 91
Const ERR_CANTMOVE = 2483
Set PrevCtl = Screen.PreviousControl
If TypeOf PrevCtl Is TextBox Then
stDialStr = IIf(VarType(PrevCtl) > V_NULL, PrevCtl, "")
ElseIf TypeOf PrevCtl Is ListBox Then
stDialStr = IIf(VarType(PrevCtl) > V_NULL, PrevCtl, "")
ElseIf TypeOf PrevCtl Is ComboBox Then
stDialStr = IIf(VarType(PrevCtl) > V_NULL, PrevCtl, "")
Else
stDialStr = ""
End If
Application.Run "utility.wlib_AutoDial", stDialStr
Exit_Command83_Click:
Exit Sub
Err_Command83_Click:
If (Err = ERR_OBJNOTEXIST) Or (Err = ERR_OBJNOTSET) Or (Err = ERR_CANTMOVE) Then
Resume Next
End If
MsgBox Err.Description
Resume Exit_Command83_Click
End Sub
Const ERR_... are Error Codes
The script checks whether PrevCtl is a Text-, List or ComboBox and sets the string of stDialStr depending on the Box. In the end it starts an external AutoDial program with the given parameter.
Application.Run "utility.wlib_AutoDial", stDialStr
I am very new with Background worker control. I have an existing project that builds file but throughout my project while building files I get the deadlock error.
I am trying to solve it by creating another project that will only consist out of the background worker. I will then merge them.
My problem is I don't know where it will be more effective for my background worker to be implemented and also the main problem is how can I use the SaveDialog with my background worker? I need to send a parameter to my background worker project telling it when my file is being build en when it is done.
This is where my file is being build:
srOutputFile = New System.IO.StreamWriter(strFile, False) 'Create File
For iSeqNo = 0 To iPrintSeqNo
' Loop through al the record types
For Each oRecord As stFileRecord In pFileFormat
If dsFile.Tables.Contains(oRecord.strRecordName) Then
' Loop through al the records
For Each row As DataRow In dsFile.Tables(oRecord.strRecordName).Rows
' Check record id
If oRecord.strRecordId.Length = 0 Then
bMatched = True
Else
bMatched = (CInt(oRecord.strRecordId) = CInt(row.Item(1)))
End If
' Match records
If iSeqNo = CInt(row.Item(0)) And bMatched Then
strRecord = ""
' Loop through al the fields
For iLoop = 0 To UBound(oRecord.stField)
' Format field
If oRecord.stField(iLoop).iFieldLength = -1 Then
If strRecord.Length = 0 Then
strTmp = row.Item(iLoop + 1).ToString
Else
strTmp = strDelimiter & row.Item(iLoop + 1).ToString
End If
ElseIf oRecord.stField(iLoop).eFieldType = enumFieldType.TYPE_VALUE Or _
oRecord.stField(iLoop).eFieldType = enumFieldType.TYPE_AMOUNT_CENT Then
strTmp = row.Item(iLoop + 1).ToString.Replace(".", "").PadLeft(oRecord.stField(iLoop).iFieldLength, "0")
strTmp = strTmp.Substring(strTmp.Length - oRecord.stField(iLoop).iFieldLength)
Else
strTmp = row.Item(iLoop + 1).ToString.PadRight(oRecord.stField(iLoop).iFieldLength, " ").Substring(0, oRecord.stField(iLoop).iFieldLength)
End If
If oRecord.stField(iLoop).iFieldLength > -1 And (bForceDelimiter) And strRecord.Length > 0 Then
strTmp = strDelimiter & strTmp
End If
strRecord = strRecord & strTmp
Next
' Final delimiter
If (bForceDelimiter) Then
strRecord = strRecord & strDelimiter
End If
srOutputFile.WriteLine(strRecord)
End If
Next
End If
Next
Next
You could try this:
Private locker1 As ManualResetEvent = New System.Threading.ManualResetEvent(False)
Private locker2 As ManualResetEvent = New System.Threading.ManualResetEvent(False)
Dim bOpenFileOK As Boolean
Dim myOpenFile As OpenFileDialog = New OpenFileDialog()
Private Sub FileOpener()
While Not bTerminado
If myOpenFile.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
bOpenFileOK = True
Else
bOpenFileOK = False
End If
locker2.Set()
locker1.WaitOne()
End While
End Sub
' Detonator of the action
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim tFileOp As Thread = New Thread(AddressOf FileOpener)
tFileOp.SetApartmentState(ApartmentState.STA)
tFileOp.Start()
' Start BackgroundWorker
BW1.RunWorkerAsync()
End Sub
Private Sub AsyncFunctionForBW(ByVal args As ArrayList)
'[...]
'Change options dinamically for the OpenFileDialog
myOpenFile.Filter = ""
myOpenFile.MultiSelect = True
'Calling the FileDialog
locker1.Set()
locker2.WaitOne()
locker1.Reset()
locker2.Reset()
If bOpenFileOK Then
myStream = myOpenFile.OpenFile()
'[...]
End If
End Sub
It's a little bit complicated but it works.
ManualResetEvents interrupt the execution of code (if they are told to stop) when reached until you use .Set(). If you use .WaitOne() you set it in stop mode, so it will stop again when reached.
This code defines two ManualResetEvents. When you click the Button1 starts the function FileOpener() in a new Thread, and then starts the BackgroundWorker. The FileOpener() function shows a FileOpenDialog and waits in the locker1 so when you use locker1.Set() the function shows the file dialog.
As the myOpenFile is a "global" variable (as well as bOpenFileOK), once the user select the file (or not) you could detect the dialog result (bOpenFileOK) and the selected file.
Is there any way, in either VBA or C# code, to get a list of the existing macros defined in a workbook?
Ideally, this list would have a method definition signatures, but just getting a list of the available macros would be great.
Is this possible?
I haven't done vba for Excel in a long time, but if I remember well, the object model for the code was inaccessible through scripting.
When you try to access it, you receive the following error.
Run-time error '1004':
Programmatic access to Visual Basic Project is not trusted
Try:
Tools | Macro | Security |Trusted Publisher Tab
[x] Trust access to Visual Basic Project
Now that you have access to the VB IDE, you could probably export the modules and make a text search in them, using vba / c#, using regular expressions to find sub and function declarations, then delete the exported modules.
I'm not sure if there is an other way to do this, but this should work.
You can take a look the following link, to get started with exporting the modules.
http://www.developersdex.com/vb/message.asp?p=2677&ID=%3C4FCD0AE9-5DCB-4A96-8B3C-F19C63CD3635%40microsoft.com%3E
This is where I got the information about giving thrusted access to the VB IDE.
Building on Martin's answer, after you trust access to the VBP, you can use this set of code to get an array of all the public subroutines in an Excel workbook's VB Project. You can modify it to only include subs, or just funcs, or just private or just public...
Private Sub TryGetArrayOfDecs()
Dim Decs() As String
DumpProcedureDecsToArray Decs
End Sub
Public Function DumpProcedureDecsToArray(ByRef Result() As String, Optional InDoc As Excel.Workbook) As Boolean
Dim VBProj As Object
Dim VBComp As Object
Dim VBMod As Object
If InDoc Is Nothing Then Set InDoc = ThisWorkbook
ReDim Result(1 To 1500, 1 To 4)
DumpProcedureDecsToArray = True
On Error GoTo PROC_ERR
Set VBProj = InDoc.VBProject
Dim FuncNum As Long
Dim FuncDec As String
For Each VBComp In VBProj.vbcomponents
Set VBMod = VBComp.CodeModule
For i = 1 To VBMod.countoflines
If IsSubroutineDeclaration(VBMod.Lines(i, 1)) Then
FuncDec = RemoveBlanksAndDecsFromSubDec(RemoveAsVariant(VBMod.Lines(i, 1)))
If LCase(Left(VBMod.Lines(i, 1), Len("private"))) <> "private" Then
FuncNum = FuncNum + 1
Result(FuncNum, 1) = FindToLeftOfString(InDoc.Name, ".") '
Result(FuncNum, 2) = VBMod.Name
Result(FuncNum, 3) = GetSubName(FuncDec)
Result(FuncNum, 4) = VBProj.Name
End If
End If
Next i
Next VBComp
PROC_END:
Exit Function
PROC_ERR:
GoTo PROC_END
End Function
Private Function RemoveCharFromLeftOfString(TheString As String, RemoveChar As String) As String
Dim Result As String
Result = TheString
While LCase(Left(Result, Len(RemoveChar))) = LCase(RemoveChar)
Result = Right(Result, Len(Result) - Len(RemoveChar))
Wend
RemoveCharFromLeftOfString = Result
End Function
Private Function RemoveBlanksAndDecsFromSubDec(TheLine As String) As String
Dim Result As String
Result = TheLine
Result = RemoveCharFromLeftOfString(Result, " ")
Result = RemoveCharFromLeftOfString(Result, " ")
Result = RemoveCharFromLeftOfString(Result, "Public ")
Result = RemoveCharFromLeftOfString(Result, "Private ")
Result = RemoveCharFromLeftOfString(Result, " ")
RemoveBlanksAndDecsFromSubDec = Result
End Function
Private Function RemoveAsVariant(TheLine As String) As String
Dim Result As String
Result = TheLine
Result = Replace(Result, "As Variant", "")
Result = Replace(Result, "As String", "")
Result = Replace(Result, "Function", "")
If InStr(1, Result, "( ") = 0 Then
Result = Replace(Result, "(", "( ")
End If
RemoveAsVariant = Result
End Function
Private Function IsSubroutineDeclaration(TheLine As String) As Boolean
If LCase(Left(RemoveBlanksAndDecsFromSubDec(TheLine), Len("Function "))) = "function " Or LCase(Left(RemoveBlanksAndDecsFromSubDec(TheLine), Len("sub "))) = "sub " Then
IsSubroutineDeclaration = True
End If
End Function
Private Function GetSubName(DecLine As String) As String
GetSubName = FindToRightOfString(FindToLeftOfString(DecLine, "("), " ")
End Function
Function FindToLeftOfString(FullString As String, ToFind As String) As String
If FullString = "" Then Exit Function
Dim Result As String, ToFindPos As Integer
ToFindPos = InStr(1, FullString, ToFind, vbTextCompare)
If ToFindPos > 0 Then
Result = Left(FullString, ToFindPos - 1)
Else
Result = FullString
End If
FindToLeftOfString = Result
End Function
Function FindToRightOfString(FullString As String, ToFind As String) As String
If FullString = "" Then Exit Function
Dim Result As String, ToFindPos As Integer
ToFindPos = InStr(1, FullString, ToFind, vbTextCompare)
Result = Right(FullString, Len(FullString) - ToFindPos + 1 - Len(ToFind))
If ToFindPos > 0 Then
FindToRightOfString = Result
Else
FindToRightOfString = FullString
End If
End Function