How to use the relative path in SQL - ODBC? - sql

I have a problem with Excel (ODBC / Access). I would like to refresh data from any folder in my computer. I have file which I use from Desktop, but I would like to refresh data from the same file when it will be move to documents, etc. Please could you provide what I should do?
I have a file connection as below:
DSN=Excel Files;DBQ=C:\Users\User\Desktop\Task1\SalesBudget2018.xlsx;DefaultDir=C:\Users\User\Desktop\Task1;DriverId=1046;MaxBufferSize=2048;PageTimeout=5;
Thank you.
EDIT1: Thank you. I tried use your solution and I received error: "run time error 2147467259 Database or object is read-only", my code below. The bug is related to ".Open" line:
Sub RefreshData()
Dim CreateNew As Object
Dim RunSELECT As Object
Dim Data As String
Dim SQL As String
FolderPath = ActiveWorkbook.path
Path = Left(FolderPath, InStrRev(FolderPath, "\") - 1)
Set CreateNew = CreateObject("ADODB.Connection")
With CreateNew
.Provider = "Microsoft.ACE.OLEDB.12.0"
.ConnectionString = "Data Source=" & Path & "\SalesBudget2018.xlsx" & ";" & "Extended Properties=""Excel 12.0 Xml;HDR=YES;"";"
.Open
End With
'Run SQL
SQL = "SELECT * FROM [twRynki$]"
Set RunSELECT = cn.Execute(SQL)
Do
output = output & RunSELECT(0) & ";" & RunSELECT(1) & ";" & RunSELECT(2) & vbNewLine
Debug.Print RunSELECT(0); ";" & RunSELECT(1) & ";" & RunSELECT(2)
rs.Movenext
Loop Until rs.EOF
End Sub

Your path actually is not relative at all. But ACE/JET data engine does not support relative paths anyway.
A relative path would be
\Data\mydb.mdb
So, above would be one folder up called data from current location. And one folder down using relative would be:
..\Data\mydb.mdb
However, with ACE/Access relative paths are not supported. However, what we do when we want software to work say from the current folder? We simple get and use the full path name ON APPLICATION start up. So, you can get/grab the current folder. In Excel VBA you can use this:
ActiveWorkbook.Path
So above will give you the current path. And thus you use that in code to set the connection string. So, even in access, if we want the software to work in any folder? We simply get/grab the full path name on startup. As a result, the software works in any folder and you effective get relative address in that you "don't care" where the software is placed, since you always get/grab the full path name anyway. So, with above, you could append a folder name called data
ActiveWorkbook.Path & "\Data\Mydb.accdb"
So, from the current workbook location, you could always have a folder called data, and inside that folder you can have your database. So, in effect you do get relative addressing, but you always pulling the full path name of the current workbook as per above.
The end result is you don't miss not having some form of relative addressing since you don't need to with this approach.
The above is for Excel VBA. To get current path from Access VBA? You can use this:
currentproject.Path
So, your connection string to Excel could be this:
dim strExcelPath as string
strExcelPath = CurrentProject.Path & "\Task1\SalesBudget2018.xlsx"
It not clear if the access application is in the SAME folder as task1?
Assuming yes, then this would work:
strExcelPath = CurrentProject.Path & "\SalesBudget2018.xlsx"
So, now the folder can be on the desktop, my documents - it will not matter. You can thus use above as part of your connection string. It not clear if you linking to Excel (linked table), or you using VBA and say ADO code. However, it really don't matter. On application startup, you get the above connection string, check it against the linked table -- if same then do nothing. If different, then you re-link that one table. Thus you ONLY re-link one time if the folder been moved. And no matter where you move the folder? As long as you assume the Excel sheet is in the same folder as the access app, then you good to go. And as noted, you could add a sub folder say ExcelSheets to above. And once again, no matter where you move this folder with the Access part, as long as the sub folder is in the same dir/folder, then this will work - despite you not having relative addressing.

Related

FileCopy in Access with wildcards

I am having a heck of a time with something that I think should be so very simple. I think age is getting to me.
All I want to do is in access, run a command that would mimic the following DOS command:
copy c:\1\ABC123-*.txt c:\1\ABC456-*.txt
It seems that filecopy does not support wildcards and for the life of me fso.copyfile just wont work (probably because I am dense). I have also tried to use the copy command using shell and cant get that to work.
To be a little clearer:
The database keeps track of parcels of land. These are "owned" by a land company. On occasion, these parcels are sold from one land company to another. When that happens we have to keep the old records and the new, so the parcel is "copied" to the new land company complete with all its payment history, etc. There are physical documents attached to that record too, and these must appear in BOTH places. I need to copy those PDF files from one parcel number to another (I already have code that duplicates the document entries in the database, I just need to fix the physical files).
So, as an example, parcel 1234 may have a deed, a latenotice, and a survey. Those files would exist as something like 1234-deed.pdf, 1234-latenotice.pdf, and 1234-survey.pdf. I need those files copied to 5678-deed.pdf, 5678-latenotice.pdf, and 5678-survey.pdf after the rest of the database copy code runs.
I need something simple, it only needs to run in that one part of the database so I do not need it to be extensible, or to create a new function, or whatever.
Thanks!
Add reference to "Microsoft Scripting Runtime".
Give this a try:
Dim F As File
Dim FSO As New FileSystemObject
Dim FromPath As String
Dim ToPath As String
FromPath = "C:\1"
ToPath = "C:\1"
Debug.Print FSO.GetFolder(FromPath).Files.Count
For Each F In FSO.GetFolder(FromPath).Files
If Instr(F.Name,"ABC123-") Then
FileCopy FromPath & "\" & F.Name, ToPath & "\" & Replace(F.Name, "123", "456")
End If
Next

Running SQL Within An Open Workbook

I'm trying to use VBA to perform some SQL operations within an open workbook. If I open the file as a read only (i.e. from an email) the code runs without issue, but if I save it locally to my desktop I get a run-time error "Cannot update. Database or object is read-only". Below is a snippet of the code I'm trying to run
Set CSVconn = New ADODB.Connection
CSVconn.ConnectionString = _
"Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & ThisWorkbook.FullName & ";" & _
"Extended Properties='Excel 12.0 Xml;HDR=yes';"
CSVConn.Open
tmprs.ActiveConnection = CSVconn
tmprs.Source = "SELECT DISTINCT [X] FROM [Range]"
tmprs.Open
Range(X).CopyFromRecordset tmprs
CSVconn.Close
I believe the problem lies with the "ThisWorkbook.FullName" portion of the connection string since the code works on my coworkers' PCs and off our company drive. The file is saved locally and the "Files On Demand" setting for OneDrive is turned off, but the file path is still listed as running through https://sharepoint.com. I've used the split function to rebuild the SharePoint address as a local C drive one (which will open the workbook if I paste the address in file explorer), but running it in VBA throws an error that the file path is not valid. I've tried switching the connection to a GUID, but Windows shut down the Scriptlet.TypeLib function as a security measure and I can't seem to get their workaround code to run. Anyone know how to fix the CSVConnection issue or how to assign a randomly generated GUID to an open workbook using VBA?

Change the path of an Excel file linked to Access 2011 with VBA

I was trying something more fancy and did post on accessforums, where I got got no responses and on programmers access, where I got links to more reading material, but which did not help me - probably due to my lack of VBA expertise.
I have done lots of other programming like PHP and Arduino, but VBA is new for me, although I been watching hours of videos, they don't quite cover what I want to do.
After 4 days of researching an failed attempts, I have simplified my approach and I would appreciate some "real" help with actual code.
Scenario:
I have multiple Excel source file with 9 tabs each.
All the source files are in the same directory, (not in the same directory as the database)
Only one source is ever linked.
Each tab of the source file is a linked table within Access.
Objective:
I wish regularly switch source files.
Method:
I want to replace only the connect file property (i.e. the full file path) for each of the 9 sheets/tabs that use the particular file.
The full path must be "picked up" from my form and applied on an event e.g. on closing of form.
Progress:
I have built a form in which I can enter the file name to use and which calculates the full path to the file in question.
I have a button on the form, which is used to close the form.
Code:
Private Sub Form_Close()
Dim dbs As Database
Dim tdf As TableDef
Dim sfl As String
Dim basePath As String
Dim sName As String
Set dbs = CurrentDb
Set sfl = "SourceData_"
Set sName = "JoeSmith"
Set basePath = "D:\Databases\BOM Consolidator\data_source"
' Loop through all tables in the database.
For Each tdf In dbs.TableDefs
If InStr(10, tdf.Connect, sfl, 1) > 10 Then
tdf.Connect = ";DATABASE=" & basePath & sfl & sName & "\" & dbs
Err = 0
On Error Resume Next
tdf.RefreshLink ' Relink the table.
If Err <> 0 Then
End If
End If
Next tdf End Sub
In the above I am entering the path etc directly just to get it working first.
Access froze :(
Help would be appreciated.
Posting this before I try a restart.
After a restart it is not freezing.
It is saying I have a missing object.
The first line is highlighted in yellow, so I assume something must go in the parenthesis, but no idea what.
If it was a function, I would normally put a variable that is not declared inside the function. This being a subroutine, I was not expecting it to ask for something...
Ultimately I will turn it into a function, sothat I can provide the file name.
A clue to what is needed on the first line please...?
Oh also I am using "Code Builder" - is that the correct option to use with closing a form?

Kill Command Deleting Wrong File(s)i

In Access VBA, I have a procedure I've put together to do this:
Allow the user to select zip file(s)
Extract any files from the zip files to the same directory (In this
specific use-case instance, it is ALWAYS extracting Excel files from
Zip files, never any change, and always using the same password)
Then I want the code to Delete the Zip file after extracting the
.xls file.
Everything works beautifully except the delete file portion. The issue is that when I tell it to delete "FileName.Zip", it is deleting "FileName.Zip" AND "FileName.xls"
Is there any way to make sure that he kill command ONLY deletes what I want it to delete? I've used it before on various occasions, and never had this happen before.
Here is the code I am using:
Dim fd As FileDialog
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim i As Variant
Set db = CurrentDb
Set rs = db.OpenRecordset("tblProjectPath")
Set fd = FileDialog(msoFileDialogFilePicker)
fd.AllowMultiSelect = True
fd.Title = "Select TOC Return File(s) to process"
fd.InitialFileName = rs.Fields("ProjectPath") & "\FilingReports\*.zip"
fd.Show
For Each i In fd.SelectedItems
'Debug.Print i
Debug.Print '------------------------'
Debug.Print i
Unzip (i) 'The bit calling the command line unzip utility to unzip the file - just telling it to extract all files to the current folder.
Debug.Print i
'Kill i
'had to take out the kill bit, b/c it was deleting both the .zip and .xls files which is not desired nor expected
If InStr(i, ".zip") Then
Kill i 'Tried to specify only .zip files even though think I shouldn't need to, but it's still deleting .xls files
End If
Next i
Edit: Add Unzip code to post:
Unzip code:
Sub Unzip(Path As String)
Dim strUnzip As String
Dim QU As String 'quotation mark
QU = Chr(34)
strUnzip = QU & "c:\program files (x86)\winzip\wzunzip" & QU & " -s" & _
"ZipPassword " & _
Path & " " '& _
Call Shell(strUnzip)
End Sub
At this point, I don't really think a "real" answer will come about. However, I'll post what I've decided to do with the particular process I'm writing this code for anyway.
I'm going to use a folder structure to divide up the files:
1. Place zip file(s)
2. Unzip files to a 2nd folder
3. After processing Excel files in 2nd folder, move to a 3rd "complete" folder.
This will get around the deleting wrong files bit.
Also, it appears that the cause for the issue is related to something to do with the call to the WinZip Command Line Unzip utility (wzunzip) in the Unzip code above, or else something with the tool itself. I thought that maybe it was b/c the tool was asking me if I wanted to overwrite existing files, but that wasn't the case, b/c I had the same issue when there were no files to overwrite.
Anyway, I'm attempting to close this one up at this point. Thanks to Wayne G. Dunn for his assistance on this.

Use a generic pathway as default

I have a small program that creates a load of files and saves to a folder specified by the user. Currently the top of the userform looks like the following when initialised:
I'd prefer if when the userform opens and also when the dialog for choosing a appears (via the Destination button) that a general default is already shown:
Can the program find the pathway to a user's desktop?
To get the path to the users desktop, use:
PathToDesktop = Environ("USERPROFILE") & "\Desktop"
If you are doing this in excel-vba, the following code would save the current workbook as a copy to the user's desktop... you can probably figure out what you're doing from there.
Dim DesktopPath As String
DesktopPath = CreateObject("WScript.Shell").SpecialFolders("Desktop") & Application.PathSeparator
ActiveWorkbook.SaveAs DesktopPath & "filename.xls"