I am attempting to download all the attachments in the Access Table and store them by Year\Month folder. I am able to download them and store them in folders by ID using the guideline from this post.
MS-Access VBA - Trying to extract each file in a table's attachments to disk?
However, now I try to modify the code a bit and it throws me an error'76' saying Path not Found. But in the code, I thought I was creating the folder already using If Len(Dir(folder, vbDirectory)) = 0 Then MkDir (folder).... also, when I hover over mkdir in debug mode, it said: folder = "C:\Personal\Desktop\a\2014\11\" which is the first couple items on my table
Can someone please help?
The table has column Year, Month, Attachments.
The goal is to place all the attachments according to Year and Month in this format: "C:\Personal\Desktop\a\YEAR\MONTH\"
Sub a()
Dim database As DAO.database
Dim table As DAO.Recordset
Dim PONum As String
Dim folder As String
Set database = CurrentDb
Dim PKey As String
Dim P2Key As String
Set table = database.OpenRecordset("NIS")
With table ' For each record in table
Do Until .EOF 'exit with loop at end of table
Set Attachments = table.Fields("Attachments").Value 'get list of attachments
PKey = table.Fields("Year").Value ' get record key
P2Key = table.Fields("Month").Value
folder = "C:\Personal\Desktop\a\" & PKey & "\" & P2Key & "\" 'initialise folder name to create
If Len(Dir(folder, vbDirectory)) = 0 Then ' if folder does not exist then create it
MkDir (folder)
End If
' Loop through each of the record's attachments'
While Not Attachments.EOF 'exit while loop at end of record's attachments
' Save current attachment to disk in the above-defined folder.
Attachments.Fields("FileData").SaveToFile (folder)
Attachments.MoveNext 'move to next attachment
Wend
.MoveNext 'move to next record
Loop
End With
End Sub
Your problem is likely that one or more of the lower-level folders does not exist. You should check for each level, the first three one at a time before the loop, then because you use year and month as further subfolders, they need to be checked also one at a time inside the loop.
folder = "C:\Personal"
If Len(Dir(folder, vbDirectory)) = 0 Then
MkDir folder
End If
folder = folder & "\Personal"
If Len(Dir(folder, vbDirectory)) = 0 Then
MkDir folder
End If
folder = folder & "\a"
If Len(Dir(folder, vbDirectory)) = 0 Then
MkDir folder
End If
With table ' For each record in table
Do Until .EOF 'exit with loop at end of table
Set Attachments = table.Fields("Attachments").Value 'get list of attachments
PKey = table.Fields("Year").Value ' get record key
If Len(Dir(folder & "\" & PKey, vbDirectory)) = 0 Then
MkDir folder * "\" & Pkey
End If
P2Key = table.Fields("Month").Value
If Len(Dir(folder & "\" & PKey & "\" & PKey2, vbDirectory)) = 0 Then
MkDir folder * "\" & Pkey & "\" & PKey2
End If
afolder = folder & "\" & PKey & "\" & P2Key ' folder name for save
' Loop through each of the record's attachments'
While Not Attachments.EOF 'exit while loop at end of record's attachments
' Save current attachment to disk in the above-defined folder.
Attachments.Fields("FileData").SaveToFile (afolder)
Attachments.MoveNext 'move to next attachment
Wend
.MoveNext 'move to next record
Loop
End With
I'm not certain, but I doubt that the parameter for .SaveToFolder expects a trailing backslash so please take note that I removed it in my alteration to your code, and also called it afolder to avoid confusion and to allow the reconstruction based on folder so if a trailing backslash is required, put it back in.
Related
I have a code to create folder or open folder if exist which works completely fine.
Now my only problem is that there can be 3 users of this database and the 3 users has individual parent folder path. They all use and share all the folders in the parent folder and has the same parent folder name, only the path is different for the parent folder.
My existing code as follows:
Private Sub Command299_Click()
Const strParent = "C:\Users\xxx\xxx\Jobs\"
Dim strJobID As String
Dim strClient As String
Dim strFolder As String
Dim fso As Object
' Create FileSystemObject
Set fso = CreateObject("Scripting.FileSystemObject")
' Get year from control - modify as needed
strClient = "(" & Me.[Client ID] & ") " & [Client Name]
' Path with year
strFolder = strParent & strClient
' Check whether folder exists
If fso.FolderExists(strFolder) = False Then
' If not, create it
fso.CreateFolder strFolder
End If
' Get student ID from control
strJobID = Me.[Job ID] & " " & [Job name]
' Full path
strFolder = strFolder & "\" & strJobID
' Check whether folder exists
If fso.FolderExists(strFolder) = False Then
' If not, create it
fso.CreateFolder strFolder
End If
' Open it
Shell "explorer.exe " & strFolder, vbNormalFocus
End Sub
As I said it does work completely fine on my computer where the const parent folder path is what is in the code, but how can I make this code work for different path?
My 1st idea was to give an "or" statement in the Const line
Const strParent = "C:\Users\xxx\xxx\Jobs\"
But it didn't want to work. Is there any way to give 3 constant path for the parent folder and if one of them exists, work from there?
Thank you for any help!
Lots of options:
If you have a file server, move the files there and use \\servername\share
If you don't have a file server, have one user share the folder and on all 3 computers, connect to the shared drive using the same letter then use that path for access.
if neither of those appeal to you, create a users table in your database with two fields, username and path. Use the Environ("USERNAME") to get the username (as above) and put the path they need in another column. lookup with
Path = DLookup("fieldUserPath", "tblUsers", "fieldUsername = '" & Environ("USERNAME") & "'")
I'm trying to set up an automatic process that scans a particular network folder for new CSV files and then appends the data to a table in Access.
A new CSV is placed in the folder everyday and they all have the same naming convention - ClosingPrice_ddmmyy with the date part changing on every file.
What's the most straight forward way to set up such a process?
All suggestions welcome!
Thanks for the reply, Rahul.
I found the following code on another forum that does most of what I want. It imports all the CSVs from within the source folder and adds them to a table within Access. However, in future I just want to add new CSVs that are added to the folder and not all the CSVs every time. Any ideas on how I can change the code to do this?
Thanks,
Sub Import_CSV()
'Modified from WillR - www.willr.info (December 2004)
Const strPath As String = "C:\ImportFolder\" 'Directory Path
Dim strFile As String 'Filename
Dim strFileList() As String 'File Array
Dim intFile As Integer 'File Number
'Loop through the folder & build file list
strFile = Dir(strPath & "*.csv")
While strFile <> ""
'add files to the list
intFile = intFile + 1
ReDim Preserve strFileList(1 To intFile)
strFileList(intFile) = strFile
strFile = Dir()
Wend
'see if any files were found
If intFile = 0 Then
MsgBox "No files found"
Exit Sub
End If
'cycle through the list of files & import to Access
'creating a new table called MyTable
For intFile = 1 To UBound(strFileList)
DoCmd.TransferText acImportDelimi, ImportSpec, _
"Raw Data", strPath & strFileList(intFile), -1
'Check out the TransferSpreadsheet options in the Access
'Visual Basic Help file for a full description & list of
'optional settings
Next
MsgBox UBound(strFileList) & " Files were Imported"
End Sub
I have created a VBA access application to find a PDF file in a folder by doing one sweep to get all the sub-folders in the root folder. Then another sweep to collect and compare all the file names to the one that is selected. We are then using the following code to open the file when it is found:
Private Sub Command132_Click()
On Error GoTo Err_Command132_Click
Dim rootFolder As String
Dim subFolder As String
Dim fileSpec As String
Dim filename As String
Dim foundfile As String
Dim filepath As String
Dim subfolders() As String
Dim co As String
Dim intSubFolderCount As Integer
rootFolder = "T:\Scanned Work Orders (Archives)\"
subFolder = Dir(rootFolder & "*.*", vbDirectory)
'*** Get subfolders in array ***
While subFolder <> ""
If subFolder <> "." And subFolder <> ".." Then
ReDim Preserve subfolders(intSubFolderCount)
subfolders(intSubFolderCount) = subFolder
intSubFolderCount = intSubFolderCount + 1
Debug.Print subFolder
End If
subFolder = Dir()
Wend
'*** Loop over array and find files ***
For intSubFolderCount = 0 To UBound(subfolders)
fileSpec = Trim(Me.Combo_History) & "*.pdf"
co = subfolders(intSubFolderCount)
filename = Dir(rootFolder & subfolders(intSubFolderCount) & "\" & fileSpec)
Do While filename <> ""
filepath = rootFolder & subfolders(intSubFolderCount)
foundfile = filepath & "\" & filename
Application.FollowHyperlink foundfile
GoTo Exit_Command132_Click
Exit Do
Loop
Next intSubFolderCount
MsgBox "No Scanned work order found for " & Me.Combo_History & "!"
Exit_Command132_Click:
Exit Sub
Err_Command132_Click:
Select Case Err.Number
Case 52
MsgBox "No Scanned work order found for " & Me.Combo_History & "!"
Case Else
MsgBox Err.Number & "-" & Err.Description
End Select
End Sub
But on some of the computers in my office they get this error message:
"Some Files can contain viruses or otherwise be harmful to your computer.
It is important to be certain that this file is from a trustworthy source.
Would you like to open this file?"
Is it possible to suppress this? We are running windows 7 professional.
This is a windows feature. Microsoft have KB on removing it here.
https://support.microsoft.com/en-us/kb/925757
It is possible to use VBA to change the registry settings, but follow the KB instructions first to ensure it solves your issue.
This question is very similar to the previously posted question: Save each sheet in a workbook to separate CSV files
However, my requirements are slightly different in that I need to have the ability to ignore specifically named worksheets (see #2 below).
I have been successful in utilizing the solution posted in this answer: https://stackoverflow.com/a/845345/1289884 which was posted in response to the question above meets almost all of my requirements with the exception of #2 below and #3 below:
I have an excel 2010 workbook that consists of multiple worksheets and I am looking for a macro that will:
Save each worksheet to a separate comma delimited CSV file.
Ignore specific named worksheet(s) (i.e. a sheet named TOC and sheet name Lookup)
Save files to a specified folder (example: c:\csv)
Ideal Solution would additionally:
Create a zip file consisting of all of the CSV worksheets within a specified folder
Any help would be greatly appreciated.
Nick,
Given you expanded on your question with the differences, and the zip part is a significant addon I have outlined a solution below that:
Creates the CSV file, skipping specific sheets using this line Case "TOC", "Lookup"
Adds them to a Zip file. This section draws heavily on Ron de Bruin's code here
The code will create the paths under StrMain and StrZipped if they do not already exists
As the ActiveWorkbook gets sub-divided into CSV files the code tests that the ActiveWorkbook is saved prior to proceeding
On (2) I ran across an issue I have seen before in my Produce an Excel list of the attributes of all MP3 files that sit in or below the "My Music" folde where the Shell.Application errored when string variables were passed to it. So I gritted my teeth and added a hardcoding of the earlier paths for Zip_All_Files_in_Folder. I commented out my earlier variable passing to show where I tried this
VBA to save CSVS
Public Sub SaveWorksheetsAsCsv()
Dim ws As Worksheet
Dim strMain As String
Dim strZipped As String
Dim strZipFile As String
Dim lngCalc As Long
strMain = "C:\csv\"
strZipped = "C:\zipcsv\"
strZipFile = "MyZip.zip"
If Not ActiveWorkbook.Saved Then
MsgBox "Pls save " & vbNewLine & ActiveWorkbook.Name & vbNewLine & "before running this code"
Exit Sub
End If
With Application
.DisplayAlerts = False
.ScreenUpdating = False
lngCalc = .Calculation
.Calculation = xlCalculationManual
End With
'make output diretcories if they don't exist
If Dir(strMain, vbDirectory) = vbNullString Then MkDir strMain
If Dir(strZipped, vbDirectory) = vbNullString Then MkDir strZipped
For Each ws In ActiveWorkbook.Worksheets
Select Case ws.Name
Case "TOC", "Lookup"
'do nothing for these sheets
Case Else
ws.SaveAs strMain & ws.Name, xlCSV
End Select
Next
'section to run the zipping
Call NewZip(strZipped & strZipFile)
Application.Wait (Now + TimeValue("0:00:01"))
Call Zip_All_Files_in_Folder '(strZipped & strZipFile, strMain)
'end of zipping section
With Application
.DisplayAlerts = True
.ScreenUpdating = True
.Calculation = lngCalc
End With
End Sub
'Create the ZIP file if it doesn't exist
Sub NewZip(sPath As String)
'Create empty Zip File
'Changed by keepITcool Dec-12-2005
If Len(Dir(sPath)) > 0 Then Kill sPath
Open sPath For Output As #1
Print #1, Chr$(80) & Chr$(75) & Chr$(5) & Chr$(6) & String(18, 0)
Close #1
End Sub
'Add the files to the Zip file
Sub Zip_All_Files_in_Folder() '(sPath As String, ByVal strMain)
Dim oApp As Object
Set oApp = CreateObject("Shell.Application")
'Shell doesn't handle the variable strings in my testing. So hardcode the same paths :(
sPath = "C:\zipcsv\MyZip.zip"
strMain = "c:\csv\"
'Copy the files to the compressed folder
oApp.Namespace(sPath).CopyHere oApp.Namespace(strMain).items
MsgBox "You find the zipfile here: " & sPath
End Sub
Is it possible using VBA to close all open files in a given directory, with out knowing filename/extension etc...
EDIT .....
I have directories linked to records, for example the record for Joe Bloggs has a directory created related to the name eg Bloggs, Joe
If the user changes the records names, the folder name therefore has to reflect this.
Currently I can change the directory name no problem if all associated files are closed. Also if these files are open I can prompt the user to close the associated files.
I was wondering would it be possible to close/ prompt to save the files?
EDIT AGAIN .....
To further complicate matters there are further directories in the directory tree that relate to each record. (I should have been clearer at the beginning, the database stores info on household insurance claims)
So you have a directory structure like so:
User Name _ID \ 1st line of Property Address _ID \ Claim No _ID
Thanks in advance for any help
Cheers
Noel
I think you can uncomplify this thing. Your Users table should have a primary key, user_id. Say Joe Bloggs' user_id is 27. Create the folder for him as C:\userdirs\27. If Joe's name is later changed, his user_id and user folder can stay the same.
If your users need access to those folders by user name rather than user_id, create shortcuts for them.
Public Function CreateUserDirShortcut(ByVal pLinkFolder As String, _
ByVal pLinkName As String, _
ByVal pTargetFolder As String) As Boolean
Dim objShell As Object
Dim objLink As Object
Dim strMsg As String
Dim blnReturn As Boolean
On Error GoTo ErrorHandler
Set objShell = CreateObject("WScript.Shell")
Set objLink = objShell.CreateShortcut(pLinkFolder & Chr(92) & pLinkName & ".lnk")
objLink.Description = pLinkName
objLink.TargetPath = pTargetFolder
objLink.Save
blnReturn = True
ExitHere:
Set objLink = Nothing
Set objShell = Nothing
CreateUserDirShortcut = blnReturn
On Error GoTo 0
Exit Function
ErrorHandler:
strMsg = "Error " & Err.Number & " (" & Err.Description _
& ") in procedure CreateUserDirShortcut"
MsgBox strMsg
blnReturn = False
GoTo ExitHere
End Function
Then you can create a shortcut to Joe Bloggs' user directory like this:
CreateUserDirShortcut "C:\shortcuts", "Bloggs, Joe", "C:\userdirs\27")