I'm in the process of setting up a Macro to open up all files in a directory and copy a certain tab from each into a combined file (merge them in one workbook). I have two problems. Firstly the files are password protected - So when I use this line it opens the file.
Set gwkbInputdata = Workbooks.Open(gRnCT_File_Loc & gsInputFileName)
However when it's password protected it fails. So I added the following to the end but it still fails.
Set gwkbInputdata = Workbooks.Open(gRnCT_File_Loc & gsInputFileName),Password = "openfile"
2nd issue - When I copy the tabs (sheets) in I want to name them with the file name I took them from. However the file name is too long - So I want to take the name up to the first space (e.g. "Test file May 13" = sheet name "Test"). How do I get this code to work.
Any help greatly appreciated.
Full code below:
* gRnCT_File_Loc = Directory location.
* gsInputFileName = File Name.
Code to date:
Sub Pulldata()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set gRwksconfigeration = Sheets(gcsConfigSheetName)
gRnCT_File_Loc = gRwksconfigeration.Range(CT_File_Loc)
gRnCT_Tab_Search = gRwksconfigeration.Range(CT_Tab_Search)
gsInputFileName = Dir(gRnCT_File_Loc)
Set gwkscurrent = ActiveWorkbook
For Each ws In ThisWorkbook.Worksheets
If ws.Name <> gcsConfigSheetName Then ws.Delete
Next ws
Do
On Error GoTo err:
Set gwkbInputdata = Workbooks.Open(gRnCT_File_Loc & gsInputFileName)
On Error GoTo 0
On Error GoTo err1:
With Sheets(gRnCT_Tab_Search)
On Error GoTo 0
End With
gsInputFileName = Dir
Loop Until gsInputFileName = vbNullString
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Exit Sub
err:
MsgBox ("No files or files in incorrect format in " & gRnCT_File_Loc)
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Exit Sub
err1:
MsgBox ("Sheet " & gRnCT_Tab_Search & " doesn't exist in file " & gsInputFileName)
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Resume Next
End Sub
For the 2nd question about getting the 1st part of the file name, try:
if(instr(gsInputFileName," ") > 0
then short_file_name=left(gsInputFileName,instr(gsInputFileName," ")-1)
else short_file_name=gsInputFileName
endif
You are missing a : after password
Set gwkbInputdata = Workbooks.Open(gRnCT_File_Loc & gsInputFileName),Password = "openfile"
should be:
Set gwkbInputdata = Workbooks.Open(gRnCT_File_Loc & gsInputFileName,Password:="openfile")
You could use split for your second problem using a space as your delimiter e.g.
Split(str, " ")(0)
where str is the original name of the file e.g. "Test file May 13"
Related
I'd like to check if a file located in my_path exists, if it does overwrite it with a file declared "garcat" containing 1 single sheet. Creating a file for the 1st time works, however overwriting it gives me this error 1004: Method 'SaveAs' of object'_Workbook' failed
Sub FileCreate(ByVal TGName As String)
Dim garcat As Workbook
Dim file As String
file = my_path
If Dir(file) <> "" Then
SetAttr file, vbNormal
Kill file
MsgBox "The file already exists, it will be replaced"
End If
Application.SheetsInNewWorkbook = 1
Set garcat = Workbooks.Add
garcat.SaveAs FileName:=file
MsgBox "File Saved"
garcat.Sheets(1).name = "GARCAT " & TGName
garcat.Close (True)
End Sub
EDIT: I set Application.DisplayAlerts = False and Application.EnableEvents = False before saving the file and I still get the pop-up error message.
This works by just telling the file to save regardless of any other factors: "And no back-talk! If there's already a file there... Just overwrite it."
Sub FileCreate(ByVal TGName As String)
Dim garcat As Workbook
Dim chemin As String
file = my_path
Application.SheetsInNewWorkbook = 1
Set garcat = Workbooks.Add
Application.DisplayAlerts = False
garcat.SaveAs FileName:=file
Application.DisplayAlerts = True
MsgBox "File Saved"
garcat.Sheets(1).name = "GARCAT " & TGName
garcat.Close (True)
I am using an interface made with Excel to allow users to concurrently edit a shared data file. To prevent multiple users from editing at the same time I made the following function to do the following:
Open the file
If the file was opened as a read-only, close the file and re-open until the file is opened as read-write or the maximum number of allowed attempts is crossed.
Function OpenTillCanEditC(refpath As String, pw As String) As Workbook
Dim wbtoopen As Workbook
Dim maxOpen As Long
Dim i As Long
Dim buttonClicked As Long
maxOpen = 10
i = 0
On Error GoTo ErrHandler:
Application.DisplayAlerts = False
Set wbtoopen = Workbooks.Open(refpath, True, Password:=pw, ReadOnly:=False)
Application.DisplayAlerts = True
While wbtoopen.ReadOnly And i < maxOpen
If wbtoopen.ReadOnly Then
wbtoopen.Close (False)
Application.Wait (Now + TimeValue("00:00:01"))
Set wbtoopen = Nothing
i = i + 1
If i >= maxOpen Then
buttonClicked = MsgBox("It appears the masterlist is currently being used by someone else. Do you want to retry opening?", vbRetryCancel)
If buttonClicked = vbRetry Then
maxOpen = maxOpen + 10
Application.DisplayAlerts = False
Set wbtoopen = Workbooks.Open(refpath, True, Password:=pw, ReadOnly:=False)
Application.DisplayAlerts = True
End If
Else
On Error GoTo ErrHandler:
Application.DisplayAlerts = False
Set wbtoopen = Workbooks.Open(refpath, True, Password:=pw, ReadOnly:=False)
Application.DisplayAlerts = True
End If
End If
Wend
Set OpenTillCanEditC = wbtoopen
Exit Function
ErrHandler:
Application.DisplayAlerts = True
If Err.Number = 1004 Then
MsgBox "The password keyed in is wrong."
Else
MsgBox "The masterlist found in " & refpath & " cannot be opened. It may be used by someone else or corrupted. If corrupted please open the file manually using Excel."
End If
Set wbtoopen = Nothing
Set OpenTillCanEditC = wbtoopen
End Function
OpenTillCanEditC will be used in a sub for updating as shown below:
Sub UpdateFile()
'Try to open
Dim datawb As Workbook
Dim filepath As String
Dim pw As String
filepath = "C:\Folder Containing File\Data File.xlsx"
pw = "password"
Set datawb = OpenTillCanEditC(filepath, pw)
If datawb Is Nothing Then
MsgBox "File cannot be opened or is currently in use."
Exit Sub
End If
'Do functions needed in the workbook here
datawb.Save()
datawb.Close
End Sub
However I keep getting either of the following two errors:
When multiple people are attempting to access the file, the OpenTillCanEditC function will still ask for a password even though it is already being keyed in.
datawb.Save() will sometimes throw an error stating that the save failed due to multiple users accessing the file.
How do I fix both of these issues to allow multiple users to edit a shared password-protected file using VBA?
I am trying to loop through all files in a folder, open them and remove document info. I am having trouble dealing with files that cannot be opened or when opened have a pop us regarding disabling macros. I tried to solve this using on error resume next and on error goto 0. But then I get a runtime failure because my workbook object (wb) has not been set when I was trying to close files that did open.
I have read the documentation on "On Error Resume Next" & "On error goto 0" but I do not believe I am using them correctly here.
Any help is greatly appreciated, Thanks.
Option Explicit
Sub test_Scrubber_New()
Dim directory As String, fileName As String, i As Variant, wb As Workbook
Application.DisplayAlerts = False
Application.ScreenUpdating = False
'directory = "C:\Users\bayli\Desktop\Files for Testing\"
directory = "C:\Users\bayli\Desktop\excel files\"
fileName = Dir(directory & "*.xl??")
i = 0
Do While fileName <> ""
On Error Resume Next
Set wb = Workbooks.Open(directory & fileName)
On Error GoTo 0
'remove info
ActiveWorkbook.RemoveDocumentInformation (xlRDIAll)
wb.Close True
i = i + 1
fileName = Dir()
Application.StatusBar = "Files Completed: " & i
Loop
Application.StatusBar = False
Application.ScreenUpdating = True
Application.DisplayAlerts = True
MsgBox "Complete"
End Sub
I updated my code to include: If Not wb Is Nothing Then remove the info as #PatricK suggested and it is working however it keeps stopping with a pop up about updating links. If I click "Do not update" my code continues working as needed but is there a way to handle this problem. I am looping through over 5k files so as you can imagine it is taking a while. The time it is taking is not a problem but currently I am sitting here having to click "dont update" quite a few times. I thought Application.DisplayAlerts = False would prevent these pop ups however it is not.
OK, so there are a couple questions here. First, regarding the error handling. When you're using inline error handling (On Error Resume Next), the basic pattern is to turn off the automatic error handling, run the line of code that you want to "catch" the error for, then test to see if the Err.Number is zero:
On Error Resume Next
ProcedureThatCanError
If Err.Number <> 0 Then
'handle it.
End If
On Error GoTo 0
The rest of the questions deal with dialogs you can encounter when you're opening workbooks. Most of this is documented on the MSDN page for Workbook.Open, but you'll want to change the Application.AutomationSecurity property to deal with the macro prompts as appropriate. For the updates, you should pass the appropriate UpdateLinks parameter. I'd also recommend specifying IgnoreReadOnlyRecommended, Notify, and CorruptLoad. Something like this should work (untested), or at least get you a lot closer:
Sub TestScrubberNew() 'Underscores should be avoided in method names.
Dim directory As String, fileName As String, i As Variant, wb As Workbook
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Dim security As MsoAutomationSecurity
security = Application.AutomationSecurity
Application.AutomationSecurity = msoAutomationSecurityForceDisable
directory = "C:\Users\bayli\Desktop\excel files\"
fileName = Dir(directory & "*.xl??")
i = 0
Do While fileName <> vbNullString
On Error Resume Next
Set wb = Workbooks.Open(fileName:=directory & fileName, _
UpdateLinks:=0, _
IgnoreReadOnlyRecommended:=True, _
Notify:=False, _
CorruptLoad:=xlNormalLoad)
If Err.Number = 0 And Not wb Is Nothing Then
On Error GoTo 0
wb.RemoveDocumentInformation xlRDIAll
wb.Close True
i = i + 1
Application.StatusBar = "Files Completed: " & i
fileName = Dir()
Else
Err.Clear
On Error GoTo 0
'Handle (maybe log?) file that didn't open.
End If
Loop
Application.AutomationSecurity = security
Application.StatusBar = False
Application.ScreenUpdating = True
Application.DisplayAlerts = True
MsgBox "Complete"
End Sub
So, I'm working on an automation project and have stumbled on a roadblock because I can't call anything on a downloaded Excel file.
When I try opening the Excel file manually, its VB Editor is disabled... All other opened Excel files have it enabled.
I'm using below for downloading/opening the said Excel (XLSX) file.
Sub GetLogins()
Application.ScreenUpdating = False
NavSheet.Unprotect [pw]
Dim LoginWkbk As Workbook, LoginWksht As Worksheet
Dim WinHTTPRequest As Object, ADOStream As Object
Dim URL As String
Dim FileRev As Long, LastRow As Long, x As Long
Dim ts As Double
ts = Timer
FileRev = [Revision] ' The current logins file revision
FileRev = FileRev + 1 ' Check for the next revision. Hah!
TryAgain:
If Password = "" Then AcctLoginsForm.Show ' Password not (yet?) supplied
' Second line of security.
If Username = "" Or Password = "" Then
' This checks if the user provided the complete information required.
' If they didn't we would clear the admin logins sheet of any information that was in there.
Call ClearAcctsSheet
MsgBox "Insufficient information submitted.", vbOKOnly, "Window_Title"
GoTo ExitSub
End If
' The logins file URL
URL = "https://mysecreturl" & FileRev & ".xlsx"
Set WinHTTPRequest = CreateObject("Microsoft.XMLHTTP")
With WinHTTPRequest
' "GET" command with username and password
.Open "GET", URL, False, Username, Password
.Send
Select Case .Status
Case 401
' Incorrect credentials.
If MsgBox("Incorrect Username/Password supplied. Try again?", vbYesNo, "Window_Title") = vbYes Then
Call ClearAcctsSheet
Password = ""
GoTo TryAgain
Else
GoTo ExitSub
End If
Case 404
' The next revision is not yet uploaded, so we set to download the previous revision
FileRev = FileRev - 1
GoTo TryAgain
Case 200
' Set the "Revision" named range to the current file revision
[Revision] = FileRev
End Select
Set ADOStream = CreateObject("ADODB.Stream")
ADOStream.Open
ADOStream.Type = 1
ADOStream.Write .ResponseBody
ADOStream.SaveToFile Environ$("temp") & "\logins.xlsx", 2 ' Save the file in the temp file overwriting if the file exists
ADOStream.Close
End With
' Need to clear out the Accounts Sheet fields before populating it with the new credentials
AcctsSheet.Range("A:C").ClearContents
Set LoginWkbk = Workbooks.Open(Environ$("temp") & "\logins.xlsx")
Set LoginWksht = LoginWkbk.Sheets(1)
LastRow = LoginWksht.Cells(Rows.Count, 1).End(xlUp).Row ' Last row. Duh.
For x = 1 To LastRow
' Copy-pasting the information from the logins file crashes Excel, hence this for-loop.
AcctsSheet.Range("A" & x).Value = LoginWksht.Range("A" & x).Value
AcctsSheet.Range("B" & x).Value = LoginWksht.Range("G" & x).Value
AcctsSheet.Range("C" & x).Value = LoginWksht.Range("H" & x).Value
Application.StatusBar = "Extraction complete. Time elapsed: " & Round(Timer - ts, 2)
If LoginWksht.Range("A" & x).Value = "" Then
Exit For
End If
Next x
LoginWkbk.Close False ' Close the logins file
Kill Environ$("temp") & "\logins.xlsx" ' Delete the logins file
[DateToday] = Format(Now, "m/d/yyyy") ' Set the "DateToday" named range to the current day.
ExitSub:
NavSheet.Protect [pw]
NavSheet.Activate
ThisWorkbook.Save
SetToNothing WinHTTPRequest, ADOStream, LoginWkbk, LoginWksht
Application.ScreenUpdating = True
End Sub
I can open the Excel file with Workbooks.Open, but the opened XLSX file is not listed in the VBAProject window so I can't call anything on the sheet.
Has anyone encountered this here? Can we force-enable the macro settings on a single workbook?
A .xlsx file cannot have macros. In my test, the VB editor is not disabled, there are just no macros in the file to show. If you have macros enabled in Excel settings, then the workbook may still need to be in a Trusted Location for Excel to allow macros to run.
MY GOAL: Batch convert all .TDM files in a folder to .XLS using an existing add-in by adapting this macro that only works 1 file at a time. (Also open to any VBA approach.)
Using an existing add-in, a single .TDM file is converted into a single .XLS workbook with multiple sheets.
I need to, instead of using a prompt to select a single .TDM file, automatically convert all .TDM files in a folder into new .XLS workbooks.
This is part of a multi-stage process. I tried various loops, mimicking other set-ups, and merging it with other code I found on various community boards.
FYI: .TDM files hold engineering data output produced by testing equipment.
Sub GetTDM_AddIn()
'Get TDM Excel Add-In
Dim obj As COMAddIn
Set obj = Application.COMAddIns.Item("ExcelTDM.TDMAddin")
'obj.Connect = True
'Confirm only importing "Description" properties for Root
Call obj.Object.Config.RootProperties.DeselectAll
Call obj.Object.Config.RootProperties.Select("Description")
'Show the group count as property
Call obj.Object.Config.RootProperties.Select("Groups")
'Select all the available properties for Group
Call obj.Object.Config.GroupProperties.SelectAll
'Import custom properties
obj.Object.Config.RootProperties.SelectCustomProperties = True
obj.Object.Config.GroupProperties.SelectCustomProperties = True
obj.Object.Config.ChannelProperties.SelectCustomProperties = True
'Let the user choose which file to import
Dim fileName
fileName = Application.GetOpenFilename("TDM & TDMS (*.tdm;*.tdms),*.tdm;*.tdms")
If fileName = False Then
' User selected Cancel
Exit Sub
End If
'Import the selected file
Call obj.Object.ImportFile(fileName)
'Record down the current workbook
Dim Workbook As Object
Set Workbook = ActiveWorkbook
End Sub
Below is an Excel Macro (VBA Script) I wrote to do something very similar to what you want to do. It converts a directory of .tdms files to their equivalent .csv files. It requires the ExcelTDM Add In (NITDMEXCEL_2015-0-0.exe) which I obtained at http://www.ni.com/example/27944/en/. I tested the script in Excel 2013 running on a modest Windows 7 Pro machine converting 24 TDMS files with 120,000 rows each file. It completed the conversions without error in about 2 minutes 30 seconds which is about 7 seconds per file. Please forgive my hasty error handling and poor VBA form.
Sub ConvertTDMStoCSV()
'
' ConvertTDMS Macro
'
' Acts upon all .tdms files in a "source" directory,
' loading each one using the ExcelTDM Add In,
' deleting the first sheet and saving the
' remaining stream data as one .csv file
' in a "target" directory. Writes a list of
' the files converted in a new sheet.
'
' Tested to work with Excel 2013 on Windows 7
' with NITDMEXCEL_2015-0-0.exe obtained at
' http://www.ni.com/example/27944/en/
Dim sourceDir As String, targetDir As String, fn As String, fnBase As String
Dim fso As Object, n As Long, resp As Integer, strNow As String, newSheet As Object
Dim tdmsAddIn As COMAddIn, importedWorkbook As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set tdmsAddIn = Application.COMAddIns.Item("ExcelTDM.TDMAddin")
tdmsAddIn.Connect = True
Call tdmsAddIn.Object.Config.RootProperties.DeselectAll
Call tdmsAddIn.Object.Config.ChannelProperties.DeselectAll
tdmsAddIn.Object.Config.RootProperties.SelectCustomProperties = False
tdmsAddIn.Object.Config.GroupProperties.SelectCustomProperties = False
tdmsAddIn.Object.Config.ChannelProperties.SelectCustomProperties = False
'Choose TDMS Source Directory
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Choose Source Directory of TDMS Files"
.AllowMultiSelect = False
.InitialFileName = ThisWorkbook.Path & "\"
.Show
On Error Resume Next
sourceDir = .SelectedItems(1)
Err.Clear
On Error GoTo 0
End With
If Dir(sourceDir, vbDirectory) = "" Then
MsgBox "No such folder.", vbCritical, sourceDir
Exit Sub
End If
'Choose CSV Target Directory
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Choose Target Directory for CSV Files"
.AllowMultiSelect = False
.InitialFileName = ThisWorkbook.Path & "\"
.Show
On Error Resume Next
targetDir = .SelectedItems(1)
Err.Clear
On Error GoTo 0
End With
If Dir(targetDir, vbDirectory) = "" Then
MsgBox "No such folder.", vbCritical, targetDir
Exit Sub
End If
fn = Dir(sourceDir & "\*.tdms")
If fn = "" Then
MsgBox "No source TDMS files found.", vbInformation
Exit Sub
End If
resp = MsgBox("Begin conversion of TDMS files?" & vbCrLf & sourceDir & vbCrLf & "to" & vbCrLf & targetDir, vbYesNo, "Confirmation")
If resp = vbNo Then
MsgBox "Execution cancelled by user."
Exit Sub
End If
Set newSheet = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
strNow = WorksheetFunction.Text(Now(), "m-d-yyyy h_mm_ss")
newSheet.Name = strNow
newSheet.Cells(1, 1).Value = "Files converted on " & strNow
newSheet.Cells(2, 1).Value = "TDMS Source Directory: " & sourceDir
newSheet.Cells(3, 1).Value = "CSV Target Directory: " & targetDir
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
n = 5
Do While fn <> ""
fnBase = fso.GetBaseName(fn)
On Error Resume Next
Call tdmsAddIn.Object.ImportFile(sourceDir & "\" & fn, True)
If Err Then
MsgBox Err.Description, vbCritical
Exit Sub
End If
Set importedWorkbook = ActiveWorkbook
Application.DisplayAlerts = False
importedWorkbook.Sheets(1).Delete
importedWorkbook.SaveAs Filename:=targetDir & "\" & fnBase & ".csv", FileFormat:=xlCSV
importedWorkbook.Close savechanges:=False
Application.DisplayAlerts = True
newSheet.Cells(n, 1).Value = fnBase
n = n + 1
fn = Dir
Loop
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Set fso = Nothing
Set newSheet = Nothing
Set importedWorkbook = Nothing
End Sub
Instead of trying to do this in VBA, I suggest that you use powershell to get all of the files and then call the Excel macro, for each file, using the Run method.
You'll also need to modify the macro to either (1) run on the current open file (solution below); or (2) take a filename as an argument (this changes the call to Run below)
The code is something like this (modify the call to get-childitem to fit your applicaton):
$excel = new-object -comobject excel.application
$files = get-childitem ... #etc, collect your files into an array
foreach ($file in $files)
{
$wb = $excel.workbooks.open($file.fullname)
$ws= $wb.worksheets.item(1)
$ws.Activate()
$excel.Run("GetTDM_AddIn")
$wb.save()
$wb.close()
}
$excel.quit()
I used this simple app to convert tdms files.
It supports multiple files and has command line support.
http://www.whiterocksoftware.com/2019/11/batch-convert-tdms-to-excel.html