I've written a macro for Excel 2010 which indexes a folder for any containing files and subfolders. The purpose of this is to manage the extraction of a particular detail from a folder directory containing hundreds of files only some of which are Excel files and of those only some of which are relevant to this detail.
The macro provides a few basic details and hyperlinks to the files (including xls, doc, pdf etc). The vba code then inserts a cell formula to extract a single cell value from a particular location of the workbooks (without opening them) where there is an Excel file and produces a #Ref! error otherwise. Since the cell formula is created through FileItem.Path and text manipulation, the formula always references the "Summary" sheet as is appropriate for the meaningful files.
The problem is that the remaining Excel files do not have a worksheet with this name which prompts Excel to deliver a popup dialog 'Select Sheet' for the user to manually choose from the options. I need a way to manage this in the vba code. I can manage a number of potential outcomes including selecting OK to choose the 1st option every time, cancelling and ignoring the request, skipping those instances etc but I cannot have the macro repeatedly interrupted for user input.
I have tried inserting Application.DisplayAlerts = False at various points in the code but it doesn't prevent that dialog.
Any help/ suggestion is greatly appreciated.
Thanks
Edit
Originally I had:
Cells(r, 5).Formula = "='" & Left(File.Path, InStr(File.Path, File.Name) - 1) & "[" & File.Name & "]Summary'!$D$3"
...producing the following cell formula:
='C:\Documents and Settings\[TEST]Summary'!$D$3
It does indeed seem that you can't disable this "invalid reference" pop-up box (please correct me if I am wrong someone!), however, what you could do is generate your formula for the reference to your "Summary" sheet in VBA (as you are already doing), but evaluate it in VBA before pasting the actual formula so that if the formula returned fine without an error then paste it, otherwise you can perform some other action instead.
For example you have at the moment:
if FileType <> "XLS" then
myCellFormula = "#Ref!"
else
myCellFormula = "[<Target File Name>]Summary!A1"
endif
However, as you know trying to put in a reference to a non-existent sheet will cause excel to cough. What you can do is check for this error in VBA, for example:
On Error Resume Next
dim dummy as variant
if FileType <> "XLS" then
myCellFormula = "#Ref!"
else
dummy = Application.Range("[<Target File Name>]Summary!A1").Value
if not isempty(dummy) then
myCellFormula = "[<Target File Name>]Summary!A1"
else
<alternative action>
endif
endif
You could also do this with an error handler, it does depend on whether you wish to skip these non-existent references (so <alternative action> would be nothing).
Edit based on your latest reply, you could change the code to something like this:
On Error Resume Next
dim dummy as variant
dim targetFileFormula as string
dim lastSlashPos as long
lastSlashPos = InStrRev(fileitem.Path, "\", , vbBinaryCompare)
targetFileFormula = "'" & Left(fileitem.Path, lastSlashPos) & "[" & Right(fileitem.Path, Len(fileitem.Path) - lastSlashPos) & "]Summary'!$D$3"
if FileType <> "XLS" then
myCellFormula = "#Ref!"
else
dummy = Application.Range(targetFileFormula).Value
if not isempty(dummy) then
myCellFormula = targetFileFormula
else
<alternative action>
endif
endif
You can then tailor this to your needs.
Related
I have the code below and it works perfectly the way I want. I type a certain phrase in Excel pop-up window using VBA to search using Google Search. However, I would love to be able to store all the Excel VBA Google searches, either in the same Excel file (same/another sheet) or in another file. Does anybody know if this is possible to do? I don't know if it's the code that should be modified or the Excel settings in some way.
Private Const LicenseRegistration As String = "+brott+och+straff"
Private Sub CommandButtonSearch_Click()
Dim query As String
Dim search_string As String
Dim googleChromePath As String
query = InputBox("Enter your keyword", "Google Search")
search_string = Replace(query, " ", "+") & LicenseRegistration
googleChromePath = "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
Shell (googleChromePath & " -url http://google.com/search?q=" & search_string)
With ThisWorkbook.Worksheets("AnotherSheet")
.Cells(.Rows.Count, 1).End(xlUp).Offset(1).Value = search_string
End With
End Sub
A window pops up titled "Microsoft Visual Basic" and it says: Run-time error "9":
Subscript out of range
I copied and pasted the code exactly as you wrote it, even tried to modify it a bit, but to no avail.
I really hope you can see the picture with this link: https://drive.google.com/file/d/1me7xBn8jGvtmpRADp5QFUFmR9k2oGzBs/view?usp=sharing
If you're just looking to keep a running list of search_string, then you can use:
With ThisWorkbook.Worksheets("AnotherSheet") ' change sheet name as needed
.Cells(.Rows.Count, 1).End(xlUp).Offset(1).Value = search_string
End With
before (or even after) the Shell call.
I am trying to read data from several shared Excel documents without opening them. They are all in the same network directory except for the file I have written.
This is a sample of the data I am pulling:
=SUMPRODUCT(COUNTIFS('[Tracker_v1.2.xlsm]Work Log'!$D:$D,B5,'[Tracker_v1.2.xlsm]Work Log'!$J:$J,{"XXXX","YYYY"}))
=SUMPRODUCT(COUNTIFS('[B Tracker_v1.1.xlsm]Work Log'!$D:$D,B6,'[B Tracker_v1.1.xlsm]Work Log'!$J:$J,{"XXXX","YYYY"})+COUNTIFS('[A Tracker_v1.1.xlsm]Work Log'!$D:$D,B6,'[A Tracker_v1.1.xlsm]Work Log'!$J:$J,{"XXXX","YYYY"}))
I have tried using file paths '\\network path\[A Tracker_v1.1.xlsm]Work Log'!
Is there a way to read data without manually opening documents?
Since you don't want to open the files manually, I suspect you might accept to open them automatically. Here's a straightforward example on how to open and close some files and perform calculations using VBA. You will still technically open the files but only for a short moment, and without actually displaying them. For the sake of illustration, assume you have two files FileA.xlsm and FileB.xlsm in the folder "C:\MyPath\" with the following data in range A1 to A3:
FileA FileB
1 4444
22 55555
333 666666
The following code will print the sum of each column in the immediate window.
Sub OpenClosedFiles()
' Opens some files, does some calculations and then closes those files.
Application.ScreenUpdating = False ' Hide the files during the microseconds while they're open.
' Define the path:
Const sPath As String = "C:\MyPath\" ' <--- Replace; don't forget the last backslash.
Dim rngA, rngB As Range
Dim sFileA, sFileB As String
Dim wbA, wbB As Workbook
sFileA = "FileA.xlsm"
sFileB = "FileB.xlsm"
Set wbA = Workbooks.Open(sPath & sFileA)
Set wbB = Workbooks.Open(sPath & sFileB)
Set rngA = wbA.Worksheets(1).Range("A1:A3")
Set rngB = wbB.Worksheets(1).Range("A1:A3")
' Do calculations on the ranges here, for example:
Debug.Print "Sum of FileA: " & Application.WorksheetFunction.Sum(rngA)
Debug.Print "Sum of FileB: " & Application.WorksheetFunction.Sum(rngB)
wbA.Close
wbB.Close
Application.ScreenUpdating = True
End Sub
You can use ADO and the Excel ODBC driver to treat closed workbooks as databases. You can then use SQL to retrieve data. But it assumes that you have information laid out in tables with table headings. AFAIK that's the only way to deal with a spreadsheet without opening it.
There's a walk through here
Would it work to link to the closed files? (In Excel 2016, click Data > Get Data > From File > From Workbook.) Then the VBA code would be only ActiveWorkbook.RefreshAll.
I'm new to VBA, but learning. I've written most of the following code myself, some of it was inherited. My goal here is to loop through multiple text files (these each contain a unique set of raw data) and copy (or in some other way transfer) that data into an analysis template that I've made which will then be "saved as" with the same filename as the raw data text file. I've been working on this for several days and have done a significant amount of searching to get this far, however, I'm currently stuck with a "Run-time type '13' error - mismatch data type" that I don't understand so I don't know how to get past it. The error is # "Data.Sheets(Sheet1).Range("A1:G180000").Copy. If I comment out the aforementioned line and the one that follows it and use the line above ("Template.Sheets(Sheet1).Range("A1:G180000").Value...") I still get the same error. My code is posted below and any help is very much appreciated. Thanks :)
Sub Shift_Load_Data_Plotter_Template()
'Josh Smith
'12/27/2013
'Shift Load Data Plotter Template
'This macro will bring up the Open dialog box so you can open multiple text files and analyze them using the Shift Load Data Plotter Template
'Brings up the Open window so you can select multiple excel files to import
Dim fn As Variant, f As Integer
Dim FileName As String
'Data is the source workbook and Template is the destination workbook
Dim Data As Workbook
Dim Template As Workbook
fn = Application.GetOpenFilename("Text files,*.txt", _
1, "Select One Or More Files To Open", , True)
If TypeName(fn) = "Boolean" Then Exit Sub
'the line below was modified from from just "workbooks.open "Z:\..." to "Set Template = Workbooks.open..."
'opens the Shift Load Data Analyzer Template workbook and sets the "Template" variable equal to said workbook
Set Template = Workbooks.Open("Z:\General Reference, Tools\Shift Load Data Analyzer Template.xlsx")
For f = 1 To UBound(fn)
'the line below was modified from just "workbooks.open fn(f)" to what it shows now
'sets the "Data" variable equal to the workbook which contains the data from the text file
Set Data = Workbooks.Open(fn(f))
FileName = ActiveWorkbook.Name
'Data.Activate
'Template.Sheets(Sheet1).Range("A1:G180000").Value = Data.Sheets(Sheet1).Range("A1:G180000").Value
Data.Sheets(Sheet1).Range("A1:G180000").Copy
Template.Sheets(Sheet1).Range("A1").PasteSpecial (xlPasteValues)
'the line below used to be "ActiveWorkbook.SaveAs..."
Template.SaveAs FileName:="Z:\" & FileName & ".xlsx"
Data.Close
Next f
End Sub
The line:
Data.Sheets(Sheet1).Range("A1:G180000").Copy
Should probably read as follows:
Data.Sheets("Sheet1").Range("A1:G180000").Copy
You need quotation marks around the sheet name if you're referring to the name (the Sheets() function is looking for the sheet name you see on the tab in Excel, not the Sheet1, Sheet2, Sheet3, etc. you see in the VBA screen). Otherwise you could write it like this:
Data.Sheet1.Range("A1:G180000").Copy
Try changing it to:
Data.Sheets(1).Range("A1:G180000").Copy
Template.Sheets(1).Range("A1").PasteSpecial (xlPasteValues)
In VBA Help for the RefersTo Property, they give this example of listing all the Names in a Wkb (fleshed out so you can run it as is)
Sub showNames()'from VBA Help for "RefersTo"
Dim newSheet As Worksheet
Set newSheet = Worksheets.Add
Dim i As Long, nm As Name
i = 1
For Each nm In ActiveWorkbook.Names
newSheet.Cells(i, 1).Value = nm.Name
newSheet.Cells(i, 2).Value = "'" & nm.RefersTo
i = i + 1
Next
newSheet.Columns("A:B").AutoFit
End Sub
When I run that on my current project, it turns up many Names that I thought were long gone. But here they are still hanging around and referring to places that no longer exist. I think this is what's slowing up my system and I'd love to get rid of those Names, but they don't show up in the Define Name window so where do I find them?
edit: Meant to mention that the Links item is greyed out for this Wbk.
Update
option 1
A manual method to delete corrupt names using R1C1 (I can recall JKP stating on another forum he had code to do this but he wasn't prepared to provide it for free)
Select Tools, Options and click the General tab.
Click the check box next to "R1C1 Reference Style", so that you change the current setting.
Press OK.
Excel will prompt you to change the name of any name (in all open workbooks!) that contains illegal characters.
Select Insert, name, define to delete the newly renamed names.
Set the R1C1 Reference style back the way you prefer using Tools, Options, General.
option 2
Chris Neilsen posted this at Any chance to delete programatically corrupt ranged names (with spaces) in Excel (2007/2010)
But, here's a possible alternative: SaveAs your workbook as a .xlsm
You should get a dialog complaining about invalid names, with a option
to rename and a Ok to All button. Once saved, close and reopen the
file, Save As an .xls and you should be good to go
Initial Post
Download Name Manager which is the stand out addin by Jan Karel Pieterse and Charles Williams for managing names
It will handle Names that
now error out as the ranges have been deleted (your issue),
link to other Workbooks,
are now corrupt
Plus it will convert global names to local sheet names, and vice versa and so on
- Updated Answer -
Since you know the names of the invalid ranges but can't see them in the Name Manager, you can try to delete them manually from the VBA Immediate window. The name you gave GrPix!patternListRange indicates a worksheet name so you should be able to delete it by typing
ActiveWorkbook.Names("GrPix!patternListRange").Delete
or
Sheets("GrPix").Names("patternListRange").Delete
in the Immediate Window
Original Answer
Have you tried deleting the invalid names via code? i.e.
For Each nm In ActiveWorkbook.Names
If InStr(nm.RefersTo, "OldFileName.xls") > 0 Then
nm.Delete
End If
Next nm
Here are two more solutions that may work for others searching on this topic, but these still don't fix my own particular Workbook.
I'm still looking.
This is from Aaron Blood and shows the R1C1 method mentioned by brettdj:
Sub RemoveDemonLinks()
Dim wbBook As Workbook
Dim nName As Name
Dim i As Long
Set wbBook = ActiveWorkbook
i = 0
If wbBook.Names.Count > 0 Then
With Application
.ReferenceStyle = xlR1C1
.ReferenceStyle = xlA1
End With
For Each nName In wbBook.Name
If InStr(nName.RefersTo, "#REF!") > 0 Then nName.Delete
i = i + 1
Next nName
If i > 0 Then MsgBox i & " corrupted names was deleted from " & wbBook.Name
End If
End Sub
This is from MS Help
' Module to remove all hidden names on active workbook
Sub Remove_Hidden_Names()
' Dimension variables.
Dim xName As Variant
Dim Result As Variant
Dim Vis As Variant
' Loop once for each name in the workbook.
For Each xName In ActiveWorkbook.Names
'If a name is not visible (it is hidden)...
If xName.Visible = True Then
Vis = "Visible"
Else
Vis = "Hidden"
End If
' ...ask whether or not to delete the name.
Result = MsgBox(prompt:="Delete " & Vis & " Name " & _
Chr(10) & xName.Name & "?" & Chr(10) & _
"Which refers to: " & Chr(10) & xName.RefersTo, _
Buttons:=vbYesNo)
' If the result is true, then delete the name.
If Result = vbYes Then xName.Delete
' Loop to the next name.
Next xName
End Sub
So, I needed to take some data done in MS Word tables, and manipulate in excel.
I decided to get it from word to excel via a VBA subroutine to "save time".
My source word document contained like twentysomething tables.
I took my source document's tables, extracted my data and made a new document, with a new table, only needing me to copy and paste it into excel.
However, while the final table before copy looks good in word. When i copy it to excel, it breaks up the cells that contain whole paragraphs into separate cells.
As most excel peeps would know, even though a solution looks like in excel, doing a merge and center - that only preserves the content in the uppermost cell in the selection!
So, any advice, on either a better merge and center, or a better "time saver" alltogether, would be great.
Here's a sample of the code so far:
Sub First()
Dim tableLength, tableIndex
tableLength = ThisDocument.Tables.Count
Dim tblReport As Table
Dim docReport As Document
Set docReport = Documents.Add
Set tblReport = docReport.Tables.Add(Selection.Range, 1, 2)
With tblReport
Dim fieldOne, subvalueAription, subvalueA, subvalueB, subvalueC
For tableIndex = 1 To tableLength
fieldOne = ThisDocument.Tables(tableIndex).Rows(2).Cells(2).Range.Text
subvalueA = Trim(ThisDocument.Tables(tableIndex).Rows(4).Cells(2).Range.Text)
subvalueB = "A: " & Trim(ThisDocument.Tables(tableIndex).Rows(5).Cells(2).Range.Text)
subvalueC = "B: " & Trim(ThisDocument.Tables(tableIndex).Rows(6).Cells(2).Range.Text)
subvalueAription = subvalueA & subvalueB & subvalueC & "C: "
Dim rowNext As row
Set rowNext = .Rows.Add
rowNext.Cells(1).Range.Text = fieldOne
rowNext.Cells(2).Range.Text = subvalueA & subvalueB & subvalueC
Next
End With
End Sub
Excel uses a different line terminator than Word. In order to avoid the problem with the text from the Word table being split over several Excel cells, you need to handle the line terminator conversion yourself.
'Word > Excel
newText = Replace(wordText, vbCrLf, vbLf)
I'm posting this by memory, but that's the root of that problem.