I have VBA code working in Excel on my machine but it is giving the above error on someone else's machine. What would be causing it to work for me but not for someone else?
'---Connecting to the Data Source---
Set cn = CreateObject("ADODB.Connection")
With cn
.Provider = "Microsoft.ACE.OLEDB.12.0"
.ConnectionString = "Data Source=" & wb.Path & "\" & wb.Name & ";" & "Extended Properties=""Excel 12.0 Xml;HDR=YES"";"
.Open
End With
'---Run the SQL SELECT Query---
sql = "SELECT " & _
"sum([" & cash_projections.Name & "$].[Projected Ending Balance]), " & _
"[" & cash_projections.Name & "$].[Account Name (Balance)], " & _
"[" & cash_projections.Name & "$].[Projected Date] " & _
"FROM " & _
"[" & cash_projections.Name & "$] " & _
"WHERE " & _
"[" & cash_projections.Name & "$].[Projected Ending Balance] > 100 " & _
"GROUP BY " & _
"[" & cash_projections.Name & "$].[Account Name (Balance)], " & _
"[" & cash_projections.Name & "$].[Projected Date] " & _
"ORDER BY " & _
"[" & cash_projections.Name & "$].[Account Name (Balance)], " & _
"[" & cash_projections.Name & "$].[Projected Date] "
Set rs = cn.Execute(sql)
The error shows up on the last line of this code. Again, it works just fine for me, but gives the error on another machine.
Please note that I am using the exact same workbook as is being used on the other computer. Here are the column headings
The line that is causing the error is the one that is executing your query. Because the code does not fail when you open the connection, it means it is finding the workbook you are querying just fine. My guess is that the workbook it finds has a different structure on the two machines. Because it says a parameter is missing a value, it means that something that is defined on your machine is missing on the other, it could be a table name or a column name. Basically, when you use that name on your machine it finds it and moves on. On the other machine, it can't find it so it assumes it must be parameter.
I am trying to find a way to run a macro every time a text file, any text file, in a certain folder is saved.
Does anyone know of a way to do that?
From: http://blogs.technet.com/b/heyscriptingguy/archive/2005/04/04/how-can-i-monitor-for-different-types-of-events-with-just-one-script.aspx
Sub Monitor()
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colMonitoredEvents = objWMIService.ExecNotificationQuery _
("SELECT * FROM __InstanceOperationEvent WITHIN 10 WHERE " _
& "Targetinstance ISA 'CIM_DirectoryContainsFile' and " _
& "TargetInstance.GroupComponent= " _
& "'Win32_Directory.Name=""c:\\\\_Stuff""'")
Do While True
Set objEventObject = colMonitoredEvents.NextEvent()
Select Case objEventObject.Path_.Class
Case "__InstanceCreationEvent"
Debug.Print "A new file was just created: " & _
objEventObject.TargetInstance.PartComponent
Case "__InstanceDeletionEvent"
Debug.Print "A file was just deleted: " & _
objEventObject.TargetInstance.PartComponent
End Select
Loop
End Sub
I have tried a lot of different things, and it seems like I cannot get it to work. So basically, this is a small piece of my complete code.
I am using Microsoft Scripting Runtime to save the file, using the FileExists() to check if the file actually exist before saving.
This is working fine if I remove the IF-statement/Loop.
However, now it feels like FileExists won´t find the string, MyFilePath, when I run it with the IF/Loop. (getdirsubparentpath is a function)
Dim week, UserName As String
Dim MyFile, MyFilePath As String
Dim version As Integer
' Current week, XX
week = Format(Date, "ww")
' Username, e.g. niclas.madsen
UserName = Environ$("UserName")
' Initials, first letter of last and surname to caps
' e.g. niclas.madsen would be NM
UserName = UCase(Left(UserName, 1) & Mid(UserName, InStr(UserName, ".") + 1, 1))
' fix filename for saving purpose
MyFile = Replace(Replace("SupplierOrganization_W", "", ""), ".", "_") _
& "" _
& week _
& " " _
& UserName _
& ".csv"
'SupplierOrganization_WXX NM
MyFilePath = getDirSubParentPath & MyFile
' Look for the MyFilePath, if it exists then
' Add "-1" after the week number, if 1 exists, add 2, etc.
If Len(Dir(MyFilePath)) <> 0 Then
version = 0
Do
version = version + 1
MyFilePath = Dir(getDirSubParentPath & "SupplierOrganization_W" & week & "-" & version & " " & UserName & ".csv")
Loop Until Len(Dir(MyFilePath)) < 0
End If
Dim tmpFile, tmpFilePath As String
tmpFile = getDirSubParentPath & "tmp_file.txt"
Dim tmpString As String
'Dim fso As New FileSystemObject
Dim fso As Object 'scripting.filesystemobject
Set fso = CreateObject("scripting.filesystemobject")
If fso.FileExists(MyFilePath) = True Then
Application.ScreenUpdating = False
Open MyFilePath For Input As #1
Open tmpFile For Output As #2
tmpString = Input(LOF(1), 1) 'read the entire file
tmpString = Replace(tmpString, (Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) _
& Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) _
& Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) _
& Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) _
& Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) _
& Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) _
& Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) _
& Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) _
& Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) _
& Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) _
& Chr(34)), "") 'eliminate double quotation and commas in the first line with UTF-8
Print #2, tmpString 'output result
Close #1
Close #2
fso.DeleteFile (MyFilePath) 'delete original file
fso.CopyFile tmpFile, MyFilePath, True 'rename temp file
fso.DeleteFile (tmpFile) 'delete temp file
Application.ScreenUpdating = True
MsgBox "Finished processing file", vbInformation, "Done!"
Else
MsgBox "Cannot locate the file : " & MyFilePath, vbCritical, "Error"
End If
Set fso = Nothing
End Sub
' Get Parent Sub Directory Path
Function getDirSubParentPath()
getDirSubParentPath = ThisWorkbook.Path & Application.PathSeparator & "CSV" & Application.PathSeparator & "Parent" & Application.PathSeparator
End Function
I finally manage to create a solution that seems viable. However, the code could use some cleaning up :) But it gets the job done.
So basically, I am having some issues with the loop. It will return a file named W16-0 (which should actual just be W16). It should only add the "-X" if W16 is found. So the incremental order should be W16, W16-1, W16-2, etc.
What I am doing is that I try to locate if there is a W16-0 and then replace it with W16. Furthermore, it seems like the loop will give me one higher than the amount of files I have. So that is where I also got an error. So if I had a W16-4, it would ask the macro to find and open a file named W16-5, which would obviously not exist.
If somebody could help me clean up the code, I would be really thankful!
Sub RemoveCommasDoubleQ()
'
' Enable a reference to 'Microsft Scripting Runtime'
' under VBA menu option Tools > References
Dim week, UserName As String
Dim MyFile, MyFilePath As String
Dim version As Integer
Dim fso As Object 'scripting.filesystemobject
Set fso = CreateObject("scripting.filesystemobject")
' Current week, XX
week = Format(Date, "ww")
' Username, e.g. niclas.madsen
UserName = Environ$("UserName")
' Initials, first letter of last and surname to caps
' e.g. niclas.madsen would be NM
UserName = UCase(Left(UserName, 1) & Mid(UserName, InStr(UserName, ".") + 1, 1))
' fix filename for saving purpose
MyFile = Replace(Replace("SupplierOrganization_W", "", ""), ".", "_") _
& "" _
& week _
& " " _
& UserName _
& ".csv"
'SupplierOrganization_WXX NM
'MyFilePath = ThisWorkbook.Path & "\CSV\Parent\" & MyFile
MyFilePath = getDirSubParentPath & MyFile
Debug.Print MyFilePath
Debug.Print "BEFORE LOOP"
'version = 1
Do While Len(Dir(MyFilePath)) <> 0
'// If it does, then append a _000 to the name
'// Change _000 to suit your requirement
MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & "-" & version & " " & UserName & ".csv"
'// Increment the counter
version = version + 1
'// and go around again
If MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & "-0" & " " & UserName & ".csv" Then
MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & " " & UserName & ".csv"
Debug.Print MyFilePath
Debug.Print "IF LOOP"
End If
Loop
Debug.Print MyFilePath
Debug.Print "LOOP"
If fso.FileExists(getDirSubParentPath & "SupplierOrganization_W" & week & "-" & version & " " & UserName & ".csv") = False Then
MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & "-" & version - 2 & " " & UserName & ".csv"
MsgBox getDirSubParentPath & "SupplierOrganization_W" & week & "-" & version & " " & UserName & ".csv"
End If
fileName = fso.GetFileName(MyFilePath)
Debug.Print fileName
If MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & "-0" & " " & UserName & ".csv" Then
MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & " " & UserName & ".csv"
Debug.Print MyFilePath
Debug.Print "her it should be 0"
End If
If MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & "-" & " " & UserName & ".csv" Then
MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & "-" & version & " " & UserName & ".csv"
End If
Debug.Print "HER ER VI"
fileName = fso.GetFileName(MyFilePath)
Debug.Print fileName
Dim tmpFile, tmpFilePath As String
tmpFile = getDirSubParentPath & "tmp_file.txt"
Dim tmpString As String
Debug.Print "------"
Debug.Print MyFilePath
If fso.FileExists(getDirSubParentPath & "SupplierOrganization_W" & week & "-0" & " " & UserName & ".csv") = True Then
MsgBox "Found the W-0"
MyFilePath = getDirSubParentPath & "SupplierOrganization_W" & week & " " & UserName & ".csv"
End If
Debug.Print "Found 0?"
Debug.Print MyFilePath
If fso.FileExists(MyFilePath) = True Then
Application.ScreenUpdating = False
Open MyFilePath For Input As #1
Open tmpFile For Output As #2
tmpString = Input(LOF(1), 1) 'read the entire file
tmpString = Replace(tmpString, (Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) _
& Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) _
& Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) _
& Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) _
& Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) _
& Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) _
& Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) _
& Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) _
& Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) _
& Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) & Chr(34) & Chr(44) & Chr(34) _
& Chr(34)), "") 'eliminate double quotation and commas in the first line with UTF-8
Print #2, tmpString 'output result
Close #1
Close #2
fso.DeleteFile (MyFilePath) 'delete original file
fso.CopyFile tmpFile, MyFilePath, True 'rename temp file
fso.DeleteFile (tmpFile) 'delete temp file
Application.ScreenUpdating = True
MsgBox "Finished processing file", vbInformation, "Done!"
Else
MsgBox "Cannot locate the file : " & MyFile, vbCritical, "Error"
End If
Set fso = Nothing
End Sub
I have the following code to monitor a drive. Now I an getting Echo for each file creation or deletion event.
Is there and way to modify the WScript.Echo to send a mail notification?
strDrive = "c"
arrFolders(0) = strDrive & "\\\\"
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
'Loop throught the array of folders setting up the monitor for Each
i = 0
For Each strFolder In arrFolders
'Create the event sink
strCommand = "Set EventSink" & i & " = WScript.CreateObject" & "(""WbemScripting.SWbemSink"", ""SINK" & i & "_"")"
ExecuteGlobal strCommand
'Setup Notification
strQuery = "SELECT * FROM __InstanceOperationEvent WITHIN 1 " & "WHERE Targetinstance ISA 'CIM_DirectoryContainsFile'" & " and TargetInstance.GroupComponent = " & "'Win32_Directory.Name=""" & strFolder & """'"
strCommand = "objWMIservice.ExecNotificationQueryAsync EventSink" & i & ", strQuery"
ExecuteGlobal strCommand
'Create the OnObjectReady Sub
strCommand = "Sub SINK" & i & "_OnObjectReady(objObject, " & "objAsyncContext)" & VbCrLf & vbTab & "Wscript.Echo objObject.TargetInstance.PartComponent" & VbCrLf & "End Sub"
WScript.Echo strCommand
ExecuteGlobal strCommand
i = i + 1
Next
WScript.Echo "Waiting for events..."
i = 0
While (True)
Wscript.Sleep(1000)
Wend
Instead of Echoing like below:
strCommand = "Sub SINK" & i & "_OnObjectReady(objObject, " & "objAsyncContext)" & VbCrLf & vbTab & "Wscript.Echo objObject.TargetInstance.PartComponent" & VbCrLf & "End Sub"
I want to send a mail like this:
strCommand = "Sub SINK" & i & "_OnObjectReady(objObject, " & "objAsyncContext)" & VbCrLf & vbTab & "
Set outobj = CreateObject("Outlook.Application")
Set mailobj = outobj.CreateItem(0)
With mailobj
.To = toAddress
.Subject = Subject
.HTMLBody = strHTML
.Send
End With
" & VbCrLf & "End Sub"
Is it possible or is there an other way to do this..?
I don't know what server do you use, but on Windows 2003 and 2008 e.g. you can use CDO object to create a email. You might use a smart host to send your email to.
Check this link: http://www.paulsadowski.com/wsh/cdo.htm
Also you can choose any free email component to create a email and use a smtp server to send your email. Or check this side where you can use a component including many examples how to do it: http://www.chilkatsoft.com/email-activex.asp.
** UPDATED **
This Script checks and send a email as you requestted:
strDrive = "d:"
Dim arrFolders(0) : arrFolders(0) = strDrive & "\\\\"
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
'Loop throught the array of folders setting up the monitor for Each
i = 0
For Each strFolder In arrFolders
'Create the event sink
WScript.Echo "setup for folder: " & strFolder & vbLf
strCommand = "Set EventSink" & i & " = WScript.CreateObject" & "(""WbemScripting.SWbemSink"", ""SINK" & i & "_"")"
ExecuteGlobal strCommand
'Setup Notification
strQuery = "SELECT * " _
& "FROM __InstanceOperationEvent " _
& "WITHIN 1 " _
& "WHERE Targetinstance ISA 'CIM_DirectoryContainsFile'" _
& " AND TargetInstance.GroupComponent = " & "'Win32_Directory.Name=""" & strFolder & """'"
strCommand = "objWMIservice.ExecNotificationQueryAsync EventSink" & i & ", strQuery"
ExecuteGlobal strCommand
'Create the OnObjectReady Sub
strCommand = "Sub SINK" & i & "_OnObjectReady(objObject, " & "objAsyncContext)" & vbLf _
& " Wscript.Echo objObject.TargetInstance.PartComponent" & vbLf _
& " SendMail(objObject.TargetInstance.PartComponent)" & vbLf _
& "End Sub"
'WScript.Echo strCommand
ExecuteGlobal strCommand
i = i + 1
Next
WScript.Echo "Waiting for events..."
i = 0
While (True)
Wscript.Sleep(1000)
Wend
Function SendMail(vBody)
Dim oMail : Set oMail = CreateObject("CDO.Message")
'Name or IP of Remote SMTP Server
oMail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
oMail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "your.smtp.server"
oMail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
oMail.Configuration.Fields.Update
oMail.Subject = "Email Watch Info Message"
oMail.From = "alert#yourdomain.net"
oMail.To = "target#yourdomain.net"
oMail.TextBody = vBody
oMail.Send
End Function
Correct the settings in the send mail function and your are fine.
In theory, the VBSendMail DLL should be able to do what you want.
I am trying to write vbs to find owner of process. Can you please help me?
My google-fu is strong
Microsoft Windows 2000 Scripting Guide - Determining Process Owners
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcessList = objWMIService.ExecQuery _
("SELECT * FROM Win32_Process")
For Each objProcess in colProcessList
colProperties = objProcess.GetOwner(strNameOfUser,strUserDomain)
Wscript.Echo "Process " & objProcess.Name & " is owned by " _
& strUserDomain & "\" & strNameOfUser & "."
Next