Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations derfloh on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Excel 2000 - Copy from 650 files 1

Status
Not open for further replies.

tallbarb

Instructor
Joined
Mar 19, 2002
Messages
90
Location
US
Have a customer who needs to copy a single cell from 650 different files into a summary workbook in Excel 2000. The cell is the same in every workbook.

This is only done once a year. The files are emailed to her and their names stay pretty much the same from year to year. However - sometimes the file names DO change (they are business files and sometimes a business goes out of business or is merged with another). They are stored in the same directory.

Any ideas on how this can be done without opening each of the 650 workbooks separately and yet not create as much or more errort than it would take to do this manually anyway?

A macro certainly does the trick - each of the files is opened & copy/paste done - and that's fine - and for eash subsequent year the macro could be used over & over. But if a file name changes, she would have to modify the macro & that makes me (and her) nervous.

I guess what I'm looking for is an easy way to do a "batch" copy of the data without referring to the individual files - copy the contents of that cell from all workbooks in a directory for instance.

Ideas??? Thanks!!!!

 
I would like to see this too. Here's where I would start though:

How about creating a text file in Notepad that has all the file names. She then can change the file name in the Notepad file which won't freak her out. Then you could write some Microsoft Scripting Runtime code that opens the file, reads the first file name and passes that to your macro code to extract the needed cell value. And then loops to the next file name. Etc. You must first set a reference to the Microsoft Scripting Runtime. You would use the TextStream Object and the Readline method.

Here's one that writes to a text file:

' Purpose: Creates a text file and stores the survey results
' in the text file.

' You must set a reference to the Microsoft Scripting Runtime
' (Tools menu, References command, check the Microsoft Scripting
' Runtime box, and then click OK).

Dim objFSO As Scripting.FileSystemObject
Dim objTS As Scripting.TextStream

' Create the text file.
Set objFSO = New Scripting.FileSystemObject
Set objTS = objFSO.OpenTextFile(CurDir & "/Survey_Results.txt", _
ForAppending, True)

' Write the results to the text file and then
' close the file.
objTS.WriteLine "Yes = " & Me.OptionButton1.Value
objTS.WriteLine "No = " & Me.OptionButton2.Value
objTS.WriteLine "Comments = " & Me.TextBox1.Text
objTS.WriteBlankLines 1
objTS.Close

' Clear the results for next time.
Me.OptionButton1.Value = False
Me.OptionButton2.Value = False
Me.TextBox1.Text = ""

Where it says objTS.Writeline, you would have objTS.ReadLine, and then pass that file name to your code.
Then loop.

Maybe this could help you a little. I have to find time to work on it.

Neil


 
The following should do it for you. You would need to simply paste it all into a module and then run the macro CopyMultipleFiles(). This is simply a very quickly skinnied down version from a something I did a few days ago with the help of Dave Peterson from the Excel newsgroups, and a great piece of code from John Walkenbach's book 'Power Programming 2002'. The bit of code from John's book allows a 'select directory' window to appear where you can choose the directory you want from a normal FileOpen type window.

It also doesn't matter if the files are in a single directory or not, so from that aspect may be a bit OTT for your need, but better to have it to start with and lose it if you don't need it. It will trawl through all folders and subfolders from whatever point you choose with the GetDirectory option.

The file will create a new summary sheet in whatever workbook you run the macro from, and will list all the data from that cell in all your files, from A3 downwards. In Col B against that same number it will put a hyperlinbk to the file it pulled the data from, so that if anything looks out of wack, it is easy to know where the data came from and to be able to open the file without a lot of searching.

The macro will pull in the data from A8 in every workbook (Change to suit), and at the moment there is an option to change the row number in the macro via an inputbox message that will appear. If you change the reference you need to change or lose the statement that will allow an amendment to the range as it currently defaults to Col A plus whatever row number you enter. You can lose it altogether, or amend it to allow the user to select a cell with the mouse as opposed to hardwiring a reference in there if you wish. You will need to change one thing though, and that is the statement:-

Set myRng = WB.Worksheets("Labour").Range

This simply referred to one of the sheets I was pulling data from in my files. Either put in the correct tab name if it is always the same, or perhaps change it to something like:-

Set myRng = WB.Worksheets(1).Range if it is always the first worksheet in the book etc.

There are a bunch of redundant DIMs in here as this is a quick and dirty skinny down of my module, but you can weed out the redundant stuff.

Thanks once again to John W, who was happy for me to post this with his code in it, and many thanks to the CD in his book which saved me having to type it out in the first place!!.



Option Explicit

Dim UserFile As String
'32-bit API declarations
Declare Function SHGetPathFromIDList Lib "shell32.dll" _
Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As String) As Long

Declare Function SHBrowseForFolder Lib "shell32.dll" _
Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long

Public Type BROWSEINFO
hOwner As Long
pidlRoot As Long
pszDisplayName As String
lpszTitle As String
ulFlags As Long
lpfn As Long
lParam As Long
iImage As Long
End Type

Function GetDirectory(Optional Msg) As String
Dim bInfo As BROWSEINFO
Dim path As String
Dim r As Long, x As Long, pos As Integer

' Root folder = Desktop
bInfo.pidlRoot = 0&

' Title in the dialog
If IsMissing(Msg) Then
bInfo.lpszTitle = "Select a folder."
Else
bInfo.lpszTitle = Msg
End If

' Type of directory to return
bInfo.ulFlags = &H1

' Display the dialog
x = SHBrowseForFolder(bInfo)

' Parse the result
path = Space$(512)
r = SHGetPathFromIDList(ByVal x, ByVal path)
If r Then
pos = InStr(path, Chr$(0))
GetDirectory = Left(path, pos - 1)
Else
GetDirectory = ""
End If
End Function


Sub CopyMultipleFiles()
' This is the macro that the button on the 'Initialise' Sheet initiates

Application.ScreenUpdating = False


Dim a As Range
Dim b As Integer
Dim lRow As Long
Dim c As Range
Dim i As Long
Dim r As Integer
Dim hyprng As String
Dim LstRow As Integer
Dim WB As Workbook
Dim CurWks As Worksheet
Dim myaddr1 As String
Dim myAddr2 As String
Dim myAddr3 As String
Dim myRng As Range
Dim myVal2 As Long
Dim myVal3 As Long
Dim Msg As String
Dim UserResp As String

On Error Resume Next


myaddr1 = "A8"
UserResp = InputBox(&quot;>>>>>>>>>> &quot; & myaddr1 & &quot; <<<<<<<<<<<&quot; & vbCrLf & vbCrLf & &quot;Is this the correct range &quot; & _
&quot;to pull in for the Summary Hours on the 'LABOUR' sheet in the BOE files. If yes then just hit &quot; & _
&quot;enter, but if not then please enter the NUMBER ONLY of the correct ROW&quot; & vbCrLf & vbCrLf & &quot; For example 20&quot;)

If UserResp = &quot;&quot; Then
myaddr1 = myaddr1
Else: myaddr1 = &quot;A&quot; & UserResp
End If


Msg = &quot;Please select a Directory to Summarise.&quot;
UserFile = GetDirectory(Msg)
If UserFile = &quot;&quot; Then
MsgBox &quot;Canceled&quot;
ElseIf Not ContinueProcedure Then
Exit Sub
End If


Set CurWks = ActiveWorkbook.Worksheets.Add


lRow = 0
With Application.FileSearch
.SearchSubFolders = True
.NewSearch
.Filename = &quot;.xls&quot;

.LookIn = UserFile
.FileType = msoFileTypeExcelWorkbooks
.Execute
For i = 1 To .FoundFiles.Count
Set WB = Application.Workbooks.Open _
(Filename:=.FoundFiles(i))



Set myRng = WB.Worksheets(&quot;Labour&quot;).Range(myaddr1)
'Bring in the hours
CurWks.Cells(lRow + 3, &quot;A&quot;) _
.Resize(myRng.Rows.Count, myRng.Columns.Count).Value _
= WB.Worksheets(&quot;Labour&quot;).Range(myaddr1).Value


'Bring in the filename
CurWks.Cells(lRow + 3, myRng.Columns.Count + 3) _
.Resize(myRng.Rows.Count).Value = WB.FullName

lRow = lRow + myRng.Rows.Count
WB.Close savechanges:=False
Next
End With


'Create hyperlinks to each of the files
Dim cell As Range, Rng As Range
Set Rng = Range(&quot;D2:I&quot; & Cells.Rows.Count).SpecialCells(xlConstants, xlTextValues)
If Rng Is Nothing Then
MsgBox &quot;nothing in range&quot;
Exit Sub
End If
For Each cell In Rng
If Trim(cell.Value) <> &quot;&quot; Then
ActiveSheet.Hyperlinks.Add Anchor:=cell, Address:=cell.Value, _
ScreenTip:=cell.Value, TextToDisplay:=cell.Value
End If
Next cell

Set myRng = Nothing
Set WB = Nothing
Set CurWks = Nothing

Application.ScreenUpdating = True


End Sub

Private Function ContinueProcedure() As Boolean
Dim Config As Integer
Dim Ans As Integer
Config = vbYesNo + vbQuestion + vbDefaultButton2
Ans = MsgBox(UserFile & &quot; <<< Is This The Correct Directory?&quot;, Config)
If Ans = vbYes Then
ContinueProcedure = True
Else: ContinueProcedure = False
End If

End Function

Regards
Ken...............
 
Absolutely wonderful - thank you!!!!
 
Glad you liked it, and appreciate the feedback - I just loved John's piece of code where the option to select a directory pops up - looks so good when others use it.

Regards
Ken.............
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top