Run-time error when deleting a named range - excel

I don't understand why I keep getting a "Run-time error '1004': Application-defined or Object-defined error" message when trying to delete a named range.
Here's the code used to import data from a .csv file and name the range as "history"
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;C:\Users\<user name>\Downloads\history.csv", Destination:=Range(destCell))
.Name = "history"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 437
.TextFileStartRow = 3
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(3, 1, 2, 1, 1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
Here's the code used to delete the "history" named range. Note that the line immediately before it functions just fine to find the named range. It just doesn't won't delete the name.
Application.Goto Reference:="history"
ActiveWorkbook.Names("history").Delete

Answer: The problem was that the Workbook was using a worksheet name as part of the Name attribute of the named range. Specifically it was using history!history for the name.
Method of Troubleshooting: I used the following code that had been posted to a similar question at http://www.ozgrid.com/forum/showthread.php?t=49079&page=2
Dim nameRng As Name
Dim varVal As Variant
On Error Resume Next
For Each nameRng In ActiveWorkbook.Names
varVal = Range(nameRng.Name).Value
nameRng.Delete
Next
The Locals Window in the VBA Editor revealed that the nameRng.Name for this variable was the string "history!history".
Revised code: I removed the Application.Goto Reference:="history" line since it was essentially a non-functional line of code (similar to a Select action) and was left with this as the code to delete the Name of the Imported range:
ActiveWorkbook.Names("history!history").Delete
Platform: I was using Excel 2013 on Windows 7 Professional

Related

Create new sheets and then import three txt files into their own columns

So backstory, I am currently copying and pasting three .txt files into their own columns per sheet. However, I have a mass amount of data so copying and pasting three .txt files into their own columns per sheet is time consuming. When I right clicked on the sheet to delete it, I saw the button "View code". In astonishment, I see an opportunity to automate this process to save tons of time. I see a vision of
specifying pathnames to the .txt files I am copying and pasting
specifying which column to paste the entire content of the .txt file
With that said, here is an example of what I would like to accomplish using the VBA system in Excel
Starting off, here are 9 .txt files that would be imported into the Worksheet:
TxtFile1Sheet1.txt
Cow1
Rabbit1
Deer1
Crab1
Goat1
Ducks1
TxtFile2Sheet1.txt
Vegetables1
Eggs1
Meat1
Poultry1
Fish1
Seeds1
TxtFile3Sheet1.txt
Fiction1
Narrative1
Novel1
Thriller1
Mystery1
Poetry1
TxtFile1Sheet2.txt
Cow2
Rabbit2
Deer2
Crab2
Goat2
Ducks2
TxtFile2Sheet2.txt
Vegetables2
Eggs2
Meat2
Poultry2
Fish2
Seeds2
TxtFile3Sheet2.txt
Fiction2
Narrative2
Novel2
Thriller2
Mystery2
Poetry2
TxtFile1Sheet3.txt
Cow3
Rabbit3
Deer3
Crab3
Goat3
Ducks3
TxtFile2Sheet3.txt
Vegetables3
Eggs3
Meat3
Poultry3
Fish3
Seeds3
TxtFile3Sheet3.txt
Fiction3
Narrative3
Novel3
Thriller3
Mystery3
Poetry3
Here is the VBA workspace that I want to use to import these txt files to their own columns.
Sub ImportThreeTxtFiles()
'
' ImportThreeTxtFiles Macro
' Import three txt files into three columns per sheet
'
'
Application.CutCopyMode = False
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;/Users/MyName/Documents/TxtFile1Sheet1", _
Destination:=Range("$A$2"))
.Name = "TxtFile1Sheet1"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.RefreshPeriod = False
.TextFilePromptOnRefresh = False
.TextFilePlatform = 10000
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = True
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
Range("B2").Select
Application.CutCopyMode = False
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;/Users/MyName/Documents/TxtFile2Sheet1", _
Destination:=Range("$B$2"))
.Name = "TxtFile2Sheet1"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.RefreshPeriod = False
.TextFilePromptOnRefresh = False
.TextFilePlatform = 10000
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = True
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
Range("C2").Select
Application.CutCopyMode = False
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;/Users/MyName/Documents/TxtFile3Sheet1", _
Destination:=Range("$C$2"))
.Name = "TxtFile3Sheet1"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.RefreshPeriod = False
.TextFilePromptOnRefresh = False
.TextFilePlatform = 10000
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = True
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
End Sub
Using this Macro I recorded, I want to import these files into their own sheets. How could I specify the three sets of files I will paste in a form of a loop? As in:
FileSet1 = TxtFile1Sheet1.txt, TxtFile2Sheet1.txt, TxtFile3Sheet1.txt
FileSet2 = TxtFile1Sheet2.txt, TxtFile2Sheet2.txt, TxtFile3Sheet2.txt
FileSet3 = TxtFile1Sheet3.txt, TxtFile2Sheet3.txt, TxtFile3Sheet3.txt
These columns will be named Animals, Type of Foods, Genres
Here is the desired output:
I am very new to VBA, I have more of a background in Python. This example is meant to be more conceptual. How would I be able to loop or call these files into these three columns? I'd love to see how the community tackles this to learn from it. I am currently watching videos and reading more about it. Thanks!
Please, test the next code and send some feedback. Take care of using the real folder path where the text file exist:
Sub ImportTextFilesInColumns()
Dim wb As Workbook, sh As Worksheet, strFoldPath As String
Dim fileName As String, shName As String, colNo As Long, arrHd, arrTxt
Set wb = ActiveWorkbook ' you can set here the workbook you need
arrHd = Split("Animals, Type of Foods, Genres", ", ") 'put the headers string in an array
strFoldPath = "Your real folder path" 'place here the folder path where the text file exist
'some optimization: _________________________________________________
Application.ScreenUpdating = False: Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'____________________________________________________________________
'Place the header on the necessary sheets:
For Each sh In wb.Sheets
Select Case sh.Name
Case "Sheet1", "Sheet2", "Sheet3"
sh.Range("A1:C1").value = arrHd
End Select
Next
'iterate between all text files in strFolder:
fileName = dir(strFoldPath & "\*.txt")
Do While fileName <> ""
colNo = CLng(Mid(fileName, 8, 1)) 'extract column number
shName = Mid(fileName, 9, 6) 'extract sheet name
'place the content of the text file in an array:
arrTxt = Split(CreateObject("Scripting.FileSystemObject").OpenTextFile(strFoldPath & "\" & fileName, 1).ReadAll, vbCrLf)
wb.Sheets(shName).cells(2, colNo).Resize(UBound(arrTxt) + 1, 1) = Application.Transpose(arrTxt) ' drop the array content
fileName = dir() 'continue the iteration between files
Loop
Application.ScreenUpdating = True: Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
MsgBox "Ready..."
End Sub
No error handling in case of no sheet with the name extracted from the last 6 digits of the text file (before .txt). You must be atentive when build the txt files name. Such an error handling can be imagined, but not treated in the above code...

VBA Excel won't copy data to sheets

I'm trying to copy the data from a hand full of CSV files into separate sheets of an excel file. I want to create one sheet per CSV file and I would like to delete the sheets if they are already present before copying over the new data (this Part seems to work fine).
Unfortunately my script doesn't seem to copy the data. The script runs without giving me an error but there still is no data in the respective tables.
Leaving out the last bit that deletes the established connection doesn't change anything.
Thank you so much in advance.
The sheet "import" looks like this:
ColumnA ColumnB
file_name sheet_name
<pathTo>\1.csv file_1
<pathTo>\2.csv file_2
<pathTo>\3.csv file_3
<pathTo>\4.csv file_4
My Macro looks like this:
Sub AddAllFiles()
Dim inputRow As Integer
For inputRow = 3 To 20
Dim fileName As String
Dim outputSheet As String
fileName = Sheets("import").Range("A" & inputRow).Value
outputSheet = Sheets("import").Range("B" & inputRow).Value
Dim checkSheetName As String
On Error Resume Next
checkSheetName = Worksheets(outputSheet).Name
If checkSheetName <> "" Then
Sheets(outputSheet).Delete
End If
Worksheets.Add.Name = outputSheet
With Sheets(outputSheet).QueryTables.Add(Connection:="TEXT" & fileName, Destination:=Sheets(outputSheet).Range("$A$1"))
.FieldName = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePlatform = 65001
.TextFilePromptOnRefresh = False
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileConsecutiveDelimiter = True
.TextFileSemicolonDelimiter = True
.TextFileTabDelimiter = False
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.TextFileTrailingMinusNumbers = True
.PreserveColumnInfo = True
End With
Dim wb_connection As WorkbookConnection
For Each wb_connection In ActiveWorkbook.Connections
If InStr(fileName, wb_connection) > 0 Then
wb_connection.Delete
End If
Next wb_connection
Next inputRow
MsgBox "Imported CSV Files"
End Sub
I changed your setup and used the Refresh function. See below. I also added the semicolon to the Connection string.
The Refresh method causes Microsoft Excel to connect to the data source of the QueryTable object, execute the SQL query, and return data to the range that is based on the QueryTable object. Unless this method is called, the QueryTable object doesn't communicate with the data source.
Therefore, the connection exists but it has not yet attempted to open connection.
Also, this method can fail. If you had left the code without the "TEXT;", you may have received an error. Just something to think about. You may want to do some error handling around it.
After the database connection is made, the SQL query is validated. If the query isn't valid, the Refresh method fails with the SQL Syntax Error exception.
With Sheets(outputSheet).QueryTables.Add(Connection:="TEXT;" & fileName, Destination:=Sheets(outputSheet).Range("$A$1"))
.CommandType = 0
.RefreshPeriod = 0
.Name = outputSheet
.FieldName = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.Refresh BackgroundQuery:=True ' This is the step I changed.
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePlatform = 65001
.TextFilePromptOnRefresh = False
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileConsecutiveDelimiter = True
.TextFileSemicolonDelimiter = False
.TextFileTabDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileTrailingMinusNumbers = True
.PreserveColumnInfo = True
.PreserveColumnInfo = True
End With
After Semicolon to "TEXT" (thanks GibralterTop)
With Sheets(outputSheet).QueryTables.Add(Connection:="TEXT;" + fileName, Destination:=Sheets(outputSheet).Range("$A$1"))
and adding
.Refresh BackgroundQuery:=False
right before the end of the with-section my problem seems to be fixed. Since I'm brand new to VBA maybe someone can enlighten me the the exact error was.

Excel VBA Import Text Array Definition problem

I have a workbook with 30 tabs of data that all follow the same process:
Go to a tab in the template workbook
Use the Data Import routine to spit out a CSV's data, dumping values on line 7 to start.
Delete line 7 when finished (it's useless headers we don't need)
The problem arises from the Import Text File routine, that needs an array for every single sheet. I end up with 40 lines of code for every sheet and no way to variablize the routine. Here's the first section of a 30-part sub (all have similar structure):
'Use the Get Data routine to dump the csv onto the sheet as text/dates where appropriate, then delete line 7
Sheets("Sheet Alpha info").Select 'explicitly declare which sheet to dump onto
Application.CutCopyMode = False 'this is good programming
'this code section is the Get Data routine run in the UI, turned into VBA
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;" & ThisWorkbook.Path & "\sheet_alpha.CSV", _
Destination:=Range("$A$7")) 'important on every tab!
'.CommandType = 0 'this is only needed when you use the UI to do the routine, so currently commented out.
.Name = "sheet_alpha" 'could variablize this routine, but signficance of .Name is unknown in Import routine.
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 437 'no idea what this actually is. encoding for UTF-8?
.TextFileStartRow = 1
.TextFileParseType = xlDelimited 'not set width
.TextFileTextQualifier = xlTextQualifierDoubleQuote 'yes, well-behaved CSV.
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True 'yes, well-behaved CSV.
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(2, 2, 2, 2, 2, 2, 2, 2, 2) 'this damn array is why we repeat the code. Need a new array for each sheet.
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
'and now remove the useless header line
Rows("7:7").Select
Selection.Delete Shift:=xlUp
So question is: How can I variablize this routine and make it a single FOR loop that also defines each TextFileColumnDataType array as a text-only array (so, Array() filled with 2s each time)?
Extension: If I wanted the array to read other data types (so an array might be Array(1, 2, 2, 3, 2, 2, 2)), how do I do that?
There are really only 3 variables here: the source file, the destination range, and the array of field types.
You could wrap this code in a sub with those 3 parameters and it should work fine. The only challenge is determining the exact field types for each file (assuming that's important here)
Sub Tester()
'eg - call directly
ImportFromText ThisWorkbook.Sheets("test").Range("A7"), _
ThisWorkbook.Path & "\test.csv", _
Array(2, 2, 2, 2, 2, 2, 2, 2, 2)
'...or from a worksheet table
Dim rw As Range
For Each rw in ThisWorkbook.Sheets("Files").Range("A2:C32").Rows
ImportFromText ThisWorkbook.Sheets(rw.Cells(1).Value).Range("A7"), _
ThisWorkbook.Path & "\" & rw.Cells(2).Value, _
Split(rw.Cells(3).Value, "|")
Next rw
End Sub
Sub ImportFromText(DestRange As Range, filePath As String, arrFieldTypes)
Dim sht As Worksheet, qt As QueryTable
Set sht = DestRange.Worksheet
'clear any previous....
Do While sht.QueryTables.Count > 0
sht.QueryTables(1).Delete
Loop
sht.UsedRange.Clear
Set qt = sht.QueryTables.Add(Connection:="TEXT;" & filePath, Destination:=DestRange)
With qt
'.CommandType = 0
.Name = "sheet_alpha"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 437
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = arrFieldTypes
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
DestRange.EntireRow.Delete Shift:=xlUp 'and now remove the useless header line
End Sub

Column getting deleted after Executing Macro in Excel 2013

I have written macro to import three columns from csv file to excel file which has 4 columns. 1 column is formulated based on 3 coming from csv file. So before running macro, there is excel file with 3 blank columns(not even column name) and 4th column with default values. Now when I run the macro, 3 columns are getting imported frm csv but 4th column is getting deleted.I don't know why this is happening. I have used Record Macro functionality to create macro. Below is my macro code:
Private Sub Workbook_Open()
Sheet11.Cells.ClearContents
With ActiveSheet.QueryTables.Add(Connection:= _
"TEXT;D:\Sample SSRS\power View\AlertHistory.csv", Destination:=Range("$A$1") _
)
.Name = "AlertHistory"
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 437
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = False
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = True
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1, 1, 1)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
End Sub
Please help.
You are clearing the entire worksheet with,
Sheet11.Cells.ClearContents
The 'default values' in the fourth column are going to be deleted along with everything else. If you only want to clear columns A through C and leave the 'default values' in column D then change that line to,
Sheet11.Cells(1, 1).Resize(1, 3).EntireColumn.ClearContents
This will not clear the entire worksheet; only columns A:C.

Using string variable as the Text connection

I am trying to write a script that loops through all the text files in a single directory and import them into Excel worksheet. They are all the same format and file type (.txt).
I have the groundwork in place for the script to successfully loop through all the files, setting the full path of each file in a string variable called FullConnection.
I know the variable is correctly setting the full path of the file because I am showing it in a message box right before where the import should happen.
My question is this:
why does the below code not work for passing in the variable as the connection name?
I'm sure it's something silly I'm doing wrong but can't seem to work it out. Hardcoding a single filepath works fine, so I know it's just the connection variable that is giving me issues.
I've seen the MSDN article on this topic but they don't show how to set a variable as the connection string, only hardcoding the actual path of the text file. Any help is appreciated!
MsgBox fullConnection
'Start importing current file into Excel:
With ActiveSheet.QueryTables.Add(Connection:="TEXT;<fullConnection>", Destination:=Range("$A$1") _
)
.Name = fullConnection
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 437
.TextFileStartRow = 4
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = True
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1, 1, 1, 1, 1, 1)
.TextFileTrailingMinusNumbers = True
'.Refresh BackgroundQuery:=False
End With
You've enveloped the path variable into the quoted string. You need to concatenate the path variable onto the right end of that quoted string.
ActiveWorkbook.Worksheets.Add
With ActiveSheet.QueryTables.Add(Connection:="TEXT;" & fullConnection, Destination:=Range("$A$1") _
)
...
I've also added a WorkSheets.Add method that should guarantee that each text file is brought into a new worksheet.

Resources