Using FileSystemObject in Access VBA - ms-access

I'm using Access 2010, and here is screenshot from my reference libraries and avalible FileSystemObject methods from within Access VB IDE:
When I initiate this object I can't seem to be able to access familiar methods, as I get exception with this example debug result:
I also used explicit declarations and initialized variables to get same results.
Any ideas what may be wrong?
To replay on #4dmonster comment, this is the actual array:
For Each p In Split("f:\temp\test\op1\gev_final_1.xlsx;f:\temp\test\op1\gev_final_2.xlsx;f:\temp\test\op1\gev_final_3.xlsx;f:\temp\test\op1\gev_final_4.xlsx;" & _
"f:\temp\test\op1\gev_final_5.xlsx;f:\temp\test\op1\gev_final_6.xlsx;f:\temp\test\op1\gev_final_7.xlsx;f:\temp\test\op2\gev_final_8.xlsx;" & _
"f:\temp\test\op2\gev_final_9.xlsx;f:\temp\test\op2\gev_final_10.xlsx;f:\temp\test\op2\gev_final_11.xlsx;f:\temp\test\op2\gev_final_12.xlsx;" & _
"f:\temp\test\op2\gev_final_13.xlsx;f:\temp\test\op3\gev_final_14.xlsx;f:\temp\test\op3\gev_final_15.xlsx;f:\temp\test\op3\gev_final_16.xlsx;" & _
"f:\temp\test\op3\gev_final_17.xlsx;f:\temp\test\op3\gev_final_18.xlsx;f:\temp\test\op3\gev_final_19.xlsx;f:\temp\test\op4\gev_final_20.xlsx;" & _
"f:\temp\test\op4\gev_final_21.xlsx;f:\temp\test\op4\gev_final_22.xlsx;f:\temp\test\op4\gev_final_23.xlsx;f:\temp\test\op4\gev_final_24.xlsx;" & _
"f:\temp\test\op5\gev_final_25.xlsx;f:\temp\test\op5\gev_final_26.xlsx;f:\temp\test\op5\gev_final_27.xlsx", ";")

The problem here is that GetFolder() is being passed a string containing the full path to a file and it is rightfully complaining that such a folder does not exist. If you want to extract the folder in which a particular file resides then you could use something like
fso.GetFile("C:\Users\Public\Database1.accdb").ParentFolder

Related

How do I detect the presence of objects using VBA in Access 2016?

I have an Access 2016 application that gets distributed to many users who are not sophisticated users. They usually have to install the MS Runtime for Access. Despite clear directions, too many users still find that the application will not open. It appears that early bound objects are not present on the system. With bound objects not present no code ever loads or runs, so it is not even possible to give a good error message.
I am now attempting to write a small program in which all the objects needed by the application are late bound, thus being able to say which modules are missing, if any. What I am finding though is that my method for detection is failing even when I KNOW the object is present. The code below is an example of one test for a required object. This test always fails and I cannot figure out why. I have about 7 of these. Three seem to work correctly, but the others do not. Is there some different way I should be coding the "CreateObject"?
Private Sub btnOffice_Click()
'Office FileDialog MSO.DLL Microsoft Office 16.0 Object Library
Dim obj As Object
On Error GoTo xyzzy
Set obj = CreateObject("Office.FileDialog")
lblOffice.Caption = "Office module present"
Exit Sub
xyzzy:
lblOffice.Caption = officeWarning
MsgBox Err.Description
End Sub
You're trying to detect broken References. Here's a procedure to check for and report broken references:
Sub CheckReferences()
Dim ref As Reference
For Each ref In References
If ref.IsBroken Then
MsgBox "Broken reference detected: " & vbCrLf & ref.Name & vbCrLf & ref.FullPath, vbOKOnly + vbCritical, "Broken Reference"
End If
Next ref
End Sub
The problem here is that the file dialog is not available as a separate COM object, and thus you can’t use CreateObject() to create such an instance.
However, if you plan to distribute your application without an office reference (and I think you safe to do so – even with runtime), then you can change the FileDialog code to late binding:
Eg this:
Dim f As FileDialog
Set f = Application.FileDialog(msoFileDialogFilePicker)
f.Show
MsgBox "file choose was " & f.SelectedItems(1)
Becomes this:
Dim f As Object
Set f = Application.FileDialog(3)
f.AllowMultiSelect = True
f.Show
MsgBox "file choosen was " & f.SelectedItems(1)
So in your case, the filedialog is not available as a separate COM object, but you can still as above shows adopt late binding anyway. However, in my experience, it IS safe to distribute the runtime with a office reference and thus at least for the office dialog you don't need late binding. For reliability, since in the case of FileDialog the late binding code is not a big deal, then I would continue distribution without the office reference for the FileDialog and use the above late binding.

Access VBA rename a file

I trying to use two textboxes to perform a rename in VBA access.
Here is my code:
Private Sub Command61_Click()
Name Me.sourFullPath As Me.destFullPath
End Sub
Both sourFullPath and destFullPath have the whole file path include the folder path and the file name + extension, they all on the same drive.
But after I ran it, Access gives me
Run-time error 5: invalid procedure call or argument.
Does anyone know what causes that?
Thanks
The syntax is correct so check what you actually are trying to do:
Private Sub Command61_Click()
Debug.Print "Source: '" & Me.sourFullPath & "' Target: '" & Me.destFullPath & "'"
Name Me.sourFullPath As Me.destFullPath
End Sub
Also, the target folder must exist.
If you look into the error code it says on
https://msdn.microsoft.com/en-us/library/aa445484(v=vs.60).aspx
•An argument probably exceeds the range of permitted values.
If you extend the destination to over 255 characters then it does fail but with an error
Run-time error '53': File not found
It still could be that your source or destination path is to long.

Access VBA not recognizing range in Excel spreadsheet

I am having a most frustrating time time with the DoCmd.TransferSpreadsheet method. I have a workbook with multiple worksheets in which users are updating data and I have a script that puts all the records back into a single sheet, links the spreadsheet, and updates the data in my Access DB. My problem is in the Range parameter. I pass the following string and get the following error:
DoCmd.TransferSpreadsheet TransferType:=acLink, SpreadsheetType:=acSpreadsheetTypeExcel12Xml, _
TableName:=linkSheet, fileName:=Wb.Path & "\" & Wb.name, _
HasFieldNames:=True, Range:="AccessUpdate!updateTable"
The Microsoft Access database engine could not find the object 'AccessUpdate$updateTable'. Make sure the object exists and that you spell its name and the path name correctly. If 'Access_Update$updateTable' is not a local object, check your network connection or contact the server administrator.
I can't seem to understand why it substitutes the dollar sign for the bang. Any other help in understanding how to specify the range would also be appreciated.
Thanks!
I know this is an year old question but it is an almost timeless problem.
I'm trying to do the same from the Excel side and bumping into the same problem. Access switching the sheet separator "!" for "$"
I found that this is a bug from Access 2000 that was never corrected. Or better, it was partially corrected at some point. So depending on your Access build and the size of the range [yes, size, since this is a bug from Access 2000] the solutions provided by Cisco or HansUp will work.
Another sources explaining the problem and a similar solution is provided by the MS$ themselves
https://answers.microsoft.com/en-us/office/forum/office_2007-access/transferspreadsheet-error-3011-can-not-file-sheet/980b2dc1-9ee1-4b3e-9c3c-a810f1428496
with the help of Bob Larson Former Access MVP (2008-2010) [see his very last post]
Now, if your range is on a different sheet with more than 65536 rows, this bug will come back.
See here for reference
Funny enough, if this is Sheet1 [yes, index 1 of all sheets] it will work with any range size. But any other sheet it wil fail.
This was my original range: BASE!A2:X68506, named REF_ACCESS. BASE is my Sheet5. Access 2010 & Excel 2010
I tried ActivateSheet, assign to string inside command, assign to string outside command, replace(,"$","!""), nothing worked. Even on Office 2016 from a friend
If I use "BASE!A2:X64506", it works. If I use "A2:X68506", Access assumes Sheet1 and works. Attention that all ranges do not have "$", but I guess you already know that
My last test was something like this monster
DoCmd.TransferSpreadsheet TransferType:=acImport, SpreadsheetType:=9, TableName:="TEST", Filename:=ThisWorkbook.FullName, HasFieldNames:=False, Range:=Worksheets("BASE").Name & "!" & Replace(Left(Worksheets("BASE").Range("REF_ACCESS").Address, Len(Worksheets("BASE").Range("REF_ACCESS").Address) - 1), "$", "")
A test that using my range within the 65536 row limit [6553 to be precise] would work. And it did.
So I see solutions with only two options for now. Either copy your range to Sheet1 or another sheet, as RyanM did, or divide your range in multiple DoCmd with 65536 rows.
I know it is long. Sorry, this was 2 full days looking for an answer without any real solution. I hope this helps other people with the same problem.
I tried multiple methods for getting around this without making major modifications to my code but with no avail. I did come up with a solution but it is rather resource intensive and messy. However, in case someone has a similar issue, I will post it here. I wound up separating my update sheet into it's own file from the rest of the workbook and linking that file. This prevented Access from trying to link a different sheet and got me around the whole Range issue. I know it's not elegant or efficient but it worked. If I figure out a cleaner way I'll post it here.
Set xl = Wb.Parent
xl.ScreenUpdating = False
xl.DisplayAlerts = False
strFile = mypath & "\TempIss.xlsx"
For i = 1 To Wb.Worksheets.count
If InStr(1, Wb.Worksheets(i).name, "Update", vbTextCompare) > 0 Then
tableId = i
Exit For
End If
Next i
If tableId = 0 Then
MsgBox "This workbook does not seem to have the necessary worksheet for updating " & _
"the Participant Issues Log in Access.", vbInformation, "Uh oh..."
Exit Function
Else
Set upWs = Wb.Worksheets(i)
upWs.Select
upWs.Copy
xl.ActiveSheet.SaveAs fileName:=strFile
xl.ActiveWorkbook.Close
Call rmSheet(Wb, "AccessUpdate")
xl.ScreenUpdating = True
linkSheet = "tempIssLog"
DoCmd.TransferSpreadsheet TransferType:=acImport, SpreadsheetType:=acSpreadsheetTypeExcel12Xml, _
TableName:=linkSheet, fileName:=strFile, _
HasFieldNames:=True
Kill (strFile)
If the range is a named range (in Excel) follow the instruction above (HansUp comment).
If the range is defined in MS-Access be sure to pass a string (something like "A1:G12") and not the control name.
Dim StrRange as variant
Dim NameofMySheet as string
NameofMySheet = "xxxxxx" ' <- Put here the name of your Excel Sheet
StrRange = NameofMySheet & "!" & "A1:G12"
DoCmd.TransferSpreadsheet TransferType:=acLink, SpreadsheetType:=acSpreadsheetTypeExcel12Xml, _
TableName:=linkSheet, fileName:=Wb.Path & "\" & Wb.name, _
HasFieldNames:=True, Range:= StrRange
Note 1: StrRange with no quotes!

Convert Windows Char Set to Cyrillic

I have a set of tables from a client that are supposed to be Cyrillic, but I guess the original coding was wrong or not set. All the text is gibberish.
If I past the text into an html page and set the encoding to Cyrillic-1251, I see the text as it should be.
Before: Ñèíèöûí À.Â.
After: Синицын А.В.
I've been looking for a VBA solution to convert the text in the tables without success. I thought this would be quick & easy, but so far no luck.
I'm running Win 7 with Access 2010
If you don't know Access, but have any VBA function to do this, I can adapt it to my needs.
Any help would be appreciated.
One possible way to solve the problem would be to export the table to CSV as code page 1252 ("ANSI") and then import it as code page 1251. I just tried that and for an existing table named [OldTable]
the following VBA code
Option Compare Database
Option Explicit
Sub DiskBounce()
Const tempFilePath = "C:\Users\Gord\Desktop\foo.csv"
DoCmd.TransferText _
TransferType:=acExportDelim, _
TableName:="OldTable", _
FileName:=tempFilePath, _
HasFieldNames:=True, _
CodePage:=1252
DoCmd.TransferText _
TransferType:=acImportDelim, _
TableName:="NewTable", _
FileName:=tempFilePath, _
HasFieldNames:=True, _
CodePage:=1251
Kill tempFilePath
End Sub
produced the following [NewTable]

Using VBA to consume WCF web service, how to change binding?

I am working on an Access 2010 'tool' that will hopefully allow me to sync our local Access database with an online one (hosted on a server that we have zero control over or direct access to). My background is not in VBA or VB.net so I am fairly new to this language so any help or suggestions would be appreciated. So far this is what I have written as a test to verify the ability to connect and to better understand what is returned when we do get a valid response.
Public Sub SendXML()
Dim myHTTP As MSXML2.ServerXMLHTTP60
Dim myDom As MSXML2.DOMDocument
Dim myXML As String
Set myHTTP = CreateObject("MSXML2.ServerXMLHTTP.6.0")
Set myDom = CreateObject("MSXML2.DOMDocument")
myDom.async = False
myXML = "<s:Envelope xmlns:a=" & Chr(34) & "http://www.w3.org/2005/08/addressing" & Chr(34) & "xmlns:s=" & Chr(34) & "http://www.w3.org/2003/05/soap-envelope" & Chr(34) & "><s:Header><a:Action s:mustUnderstand=" & Chr(34) & "1" & Chr(34) & ">http://tempuri.org/IWcfService/Get_InitiativeList_CSV</a:Action></s:Header><s:Body><Get_InitiativeList_CSV xmlns=" & Chr(34) & "http://tempuri.org/" & Chr(34) & "><userID>MYUSERID</userID></Get_InitiativeList_CSV></s:Body></s:Envelope>"
myDom.LoadXML (myXML)
myHTTP.Open "post", "https://server/WcfService/WcfService.svc", False
myHTTP.setRequestHeader "Content-Type", "application/xml"
'myHTTP.send (myDom.XML)
myHTTP.send (myXML)
MsgBox myHTTP.responseText
End Sub
I get back:
The server cannot service the request because the media type is unsupported.
A couple things to note above. I tried two different way to create the XML string. One creating it as you see above and sending that raw text to the server. And creating the string as you see above and using loadXML to create the string. I do not know why one would be better than the other but both returned the same error.
Now, I have tried SOA Cleaner Express and am able to connect successfully to the service and get data back. Since SOA Cleaner is able to connect I figured using the RAW SOAP/XML string SOA sends in VBA might be a good starting point. I noticed that using SOA cleaner it has a WCF Binding as WsHttpBinding and if I change this binding to BasicHttpBindingI get a similar error message as I am getting in VBA, to be exact:
Content Type text/xml; charset=utf-8 was not supported by service
Not even sure I am going in the right direction, but if I am, how do I set or change the 'binding' in VBA? Is there something else going on here? I am sure it is something simple, but like I said I do not have a VBA background, and WCF and SOAP are somewhat new to me as well.
I appreciate any assistance.
For starters, the binding from the client must match the service, so if the service only supports wsHttpBinding, the client must use that as well.
For added flexiblity calling a WCF service from VBA, including the ability to specify the binding, you may want to use monikers instead. Here is an example of service monkier being constructed and used in VBA:
Dim addr As String
addr = "service:mexAddress=""net.tcp://localhost:7891/Test/WcfService1/Service1/Mex"","
addr = addr + "address=""net.tcp://localhost:7891/Test/WcfService1/Service1/"","
addr = addr + "contract=""IService1"", contractNamespace=""http://tempuri.org/"","
addr = addr + "binding=""NetTcpBinding_IService1"", bindingNamespace=""http://tempuri.org/"""
Dim service1 As Object
Set service1 = GetObject(addr)
MsgBox service1.GetData(12)
Here are some links with more info, including the source of this code snippet:
http://msdn.microsoft.com/en-us/library/ms752245(v=vs.110).aspx
http://damianblog.com/2009/07/05/excel-wcf/
This may be far-fetched, but given that the second error is more descriptive than the first error, have you tried specifying the charset?
myHTTP.setRequestHeader "Content-Type", "application/xml; charset=utf-8"