I have this Macro that copies one sheet from another Workbook that i open via a File Dialog. It is supposed to sort and delete the Rows whose A Column does not possess data in an Array I've defined. It appears to be copying and pasting the data properly but when it runs through the loop to delete the data that doesn't contain the items in the array it ends up clearing the entire sheet
This Macro worked last Friday when I left for the day but now it seems it no longer works. I've tried stepping through the code but the loop doesn't appear to change much so I'm unsure why it stopped working over the weekend.
Public filepath As String
Sub SPOMacro()
'Display a Dialog Box that allows to select a single file.
'The path for the file picked will be stored in fullpath variable
With Application.FileDialog(msoFileDialogFilePicker)
'Makes sure the user can select only one file
.AllowMultiSelect = False
'Filter to just the following types of files to narrow down selection options
.Filters.Add "Excel Files", "*.xlsx; *.xlsm; *.xls; *.xlsb", 1
'Show the dialog box
.Show
'Store in fullpath variable
fullPath = .SelectedItems.Item(1)
End With
filepath = fullPath
'It's a good idea to still check if the file type selected is accurate.
'Quit the procedure if the user didn't select the type of file we need.
If InStr(fullPath, ".xls") = 0 Then
Exit Sub
End If
'Open the file selected by the user
'Workbooks.Open fullpath
'This is the Copy Sheet Portion
'MsgBox filepath
Dim spo_book As Workbook
Dim target_book As Workbook
Set spo_book = Workbooks("SPO_Untimed_Report.xlsm")
Set target_book = Workbooks.Open(filepath)
Dim dst_sheet As Worksheet
Dim target_sheet As Worksheet
Set dst_sheet = spo_book.Sheets("SPO Data")
Set target_sheet = target_book.Sheets("Untimed Parts")
dst_sheet.Cells.Clear
dst_sheet.Cells.Delete
Z = Cells(Sheets("Untimed Parts").Rows.Count, 1).End(xlUp).Row
target_sheet.Range("A1:R" & Z).Copy
dst_sheet.Range("A1").PasteSpecial
' Sort Pasted Data by Cost Ctr
Dim dontDelete
dontDelete = Array("RX01225", "RX01303", "RX01304", "RX01314", "RX01338", "Cost Ctr")
dst_sheet.Activate
Dim i As Long, j As Long
Dim isThere As Boolean
For i = Range("A" & Rows.Count).End(xlUp).Row To 1 Step -1
For j = LBound(dontDelete) To UBound(dontDelete)
If StrComp(Range("A" & i), dontDelete(j), vbTextCompare) = 0 Then
isThere = True
End If
Next j
If Not isThere Then
Range("A" & i).Delete shift:=xlUp
End If
isThere = False
Next i
'Deletes Blank Rows
Columns("A").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End Sub
The expected outcome is that the workbook that I called SPO Untimed will keep the sheet called SPO Data and the data that is pasted into that sheet from the Selected Workbook (By the File Dialog) is sorted by the Array I've defined and only the rows that have those items in the A Column remain.
Related
this is the code that i am currently using right now, but its not enough to meet my objectives and i am stuck on how to continue....
So this code will copy the specified data from many other excel workbook in the form of xlsx into a main excel workbook and before that it will scan through the folder which contains all the different data files and the main file(all files supposed to be transfered here in a table form) e.g. Test3.xlsx,Test4.xlsx,Test.xlxs and Main.xlsm in the folder of ScanFiles. so everytime a new files comes into the folder, it will automatically update the main workbook by opening the data workbooks then copy the required data and paste it on the main workbook upon clicking a button.
Sub ScanFiles()
Dim myFile As String, path As String
Dim erow As Long, col As Long
path = "c:\Scanfiles\"
myFile = Dir(path & "*.xlsx")
Application.ScreenUpdating = False
Do While myFile <> ""
Workbooks.Open (path & myFile)
Windows(myFile).Activate
Set copyrange = Sheets("sheet1").Range("A18,B18,C18,D18,A19,B19,C19,D19")
Windows("master-wbk.xlsm").Activate
erow = Sheet1.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
col = 1
For Each cel In copyrange
cel.Copy
Cells(erow, col).PasteSpecial xlPasteValues
col = col + 1
Next
Windows(myFile).Close savechanges:=False
myFile = Dir()
Loop
Range("A:E").EntireColumn.AutoFit
Application.ScreenUpdating = True
End Sub
Objectives: 1st:orignal type of file is in "file" not xlsx, so hope to find a way to open the file in xlsx format automatically before start of copying data.
2nd: requires 3 types of specified data e.g. name,surname(both of them are in fixed position always in A18 to D18 and A19 to D19 , 3rd one is to find the date, however the date is almost always in different positions in the data sheet, so i hope to add on a part to the code that makes it search for something like "ended 20190808" it will always start with ended but will always be in diff rows or even columns. i also need to arrange the data according to the date from newest(top) to oldest(bottom) and state the month of the date in words instead of numbers e.g. june
Deeply Appreciate any form of help but if possible the small section of code that can add on to my coding will make it a lot easier because im tasked to do this in a very limited amount of time
Thank you!!!
Here's some code that does similar things to what you describe. The animated .gif shows it working by stepping through the code. First the 2 data (.xlsx) files are shown so you have an idea of their content. Each is located in the same folder as the main workbook and has data in column A. Then as we step through the code each file is opened, its data manipulated (row 3 is deleted) and transferred into adjacent columns of the main workbook. The code is not limited to .xlsx files and will work with text files as well, as long as ext is defined.
Hopefully, once you understand how this works you can modify it to apply it to your case.
Option Explicit
Sub CombineFiles()
Dim theDir As String, numFiles As Integer
Dim sh As Worksheet, wk As Workbook, newSheet As Worksheet
Dim newColumn As Range, r As Range, s As String
Const ext = ".xlsx"
Err.Clear
theDir = ThisWorkbook.Path
Set newSheet = ThisWorkbook.Sheets.Add
newSheet.Name = "Combined"
Set newColumn = newSheet.Range("A1")
'Loop through all files in directory
s = Dir(theDir & "\*" & ext)
While s <> ""
numFiles = numFiles + 1
On Error Resume Next
Set wk = Workbooks.Open(theDir & "\" & s)
Set sh = ActiveSheet
sh.Rows(3).Delete Shift:=xlUp
Set r = Range("A1")
Range(r, r.End(xlDown)).Copy
newSheet.Activate
newColumn.Offset(0, numFiles) = wk.Name
newColumn.Offset(1, numFiles).Select
newSheet.Paste
Application.DisplayAlerts = False
wk.Close False
Application.DisplayAlerts = True
s = Dir()
Wend
MsgBox (numFiles & " files were processed.")
End Sub
For copy/paste of pictures see examples on this or this page. To find the last cell containing data in a column see this page; note that one example involves using the .find command. More generally, to learn how to use .find in vba, use the macro recorder and then adjust the resulting code.
I have three files. One excel file that is empty and contains my Macro. Second excel file that has about 20 tabs with updated data (Variable "UpdatedFiles" contains the file path) that needs to by copy/pasted into my third excel file (Variable "ProvisionFiles" contains the file path), that has extra tabs that link to the tabs that I am copy/pasting in.
My code works great right up to the point that I hit the Copy/Paste Section of my For Each Loop. Note that the tabs that I am copying over have the overlapping/same tab names in both workbooks.
I have tried to copy/paste data with all three methods described in this video. https://www.excelcampus.com/vba/copy-paste-cells-vba-macros/
Still can't get it to work.
`Sub CopyPasteData()
Dim ProvisionFile As String 'String File Path of Provision File
Dim UpdatedFile As String 'String File Path of Updated OneSource Files
Dim ws As Worksheet 'Used to Loop Though WS Tabs in Updated OneSource Files
Dim wsName As String 'Name of Tab of OneSource File
Dim lastRow As Long
Dim lastColumn As Long
'Open Dialog Box that allows you to Select the Provision File
MsgBox "Select your provision file, which is the destination for the updated OneSource Reports. Please ensure this file is closed before opening."
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = False
.Title = "Select file"
.InitialFileName = "C:\"
If .Show = -1 Then
'ok clicked
ProvisionFile = .SelectedItems(1)
Workbooks.Open(ProvisionFile).Activate
'Worksheets("Control").Activate
Else
'cancel clicked
End If
End With
'Get updated Reports
MsgBox "Select the file that contains the updated OneSource Reports."
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = False
.Title = "Select file"
.InitialFileName = "C:\"
If .Show = -1 Then
'ok clicked
UpdatedFile = .SelectedItems(1)
Workbooks.Open(UpdatedFile).Activate
Else
'cancel clicked
End If
End With
'Loop through Each tab in Updated File
For Each ws In Worksheets
wsName = ws.Name
lastRow = Sheets(wsName).Cells(Rows.Count, 1).End(xlUp).Row
lastColumn = Sheets(wsName).Cells(7, Columns.Count).End(xlToLeft).Column
'Debug.Print ("Yes")
Workbooks(ProvisionFile).Worksheets(wsName).Range(Workbooks(ProvisionFile).Worksheets(wsName).Cells(1, 1), Workbooks(ProvisionFile).Worksheets(wsName).Cells(lastRow, lastColumn)) = Sheets(wsName).Range(Sheets(wsName).Cells(1, 1), Sheets(wsName).Cells(lastRow, lastColumn))
Next ws
End Sub`
Expected result is to finish the copy/paste loop.
Error I am recieving = Run-time error'9': Subscript out of range
When dynamically creating textboxes/comboboxes on a userform, I create a combobox with information in another Excel workbook. (Not in the workbook I created the code/userform in. Nor can it be because it may change/get issued in the future & I don't want to have to move code into it).
After I create the combobox, I call another sub, Populate_Steel_List, to populate it. After everything has been generated, when tabbing through the textboxes/comboboxes actual Tab values are being placed in the textboxes/comboboxes, instead of moving on to the next textbox/combobox on the userform!
If I comment out calling for Populate_Steel_List, the userform's tabbing works fine. So I know calling it is causing the problem.
I tried adding a For-Next (For Each-Next as well) loop for each control, setting the .TabKeyBehavior = False. It didn't seem to do anything.
Here is my code:
Private Sub NumberMembers_Change()
' ....there is some other code in this sub, but has been tested,
' ie. commented out, till I found out
' where the offending code actually is
Dim TextBox8 As Object ' have also tried As Control; both run fine,
' but neither fix TabKeyBehavior on the userform
' Create Member Cross Section List Textboxes
Set TextBox8 = Controls.Add("Forms.ComboBox.1")
With TextBox8
.Name = "MemberSectionList" & i
.height = 17
.Width = 90
.Left = 494
.Top = 20 * i
.TabIndex = NextTabNumber + 3
End With
TextBox8Name(i) = TextBox8.Name
MembSectCurrBox = TextBox8.Name
Populate_Steel_List 'If I comment this out, the problem goes away,
' but that's not gonna work
End Sub
' ...and here's the code for Populate_Steel_List
Private Sub Populate_Steel_List()
Dim fd As Office.FileDialog
'Dim TextFile As Integer
' Check to see if log file has already been created
' Skip to using the path to find the excel document to have VBA read from it
If Len(FilePathToAISCShapesDatabase) > 0 Then GoTo Skip
If FilePathToAISCShapesDatabase = vbNullString Then
ChDir (Replace(ActiveWorkbook.FullName, ActiveWorkbook.Name, ""))
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.AllowMultiSelect = False
' Set the title of the dialog box.
.Title = "Please select the latest AISC shapes database file."
' Clear out the current filters, and add our own.
.Filters.Clear
.InitialFileName = "AISC Shapes Database v14.1.xlsm"
.Filters.Add "Excel", "*.xlsm, *.xlsx"
.Filters.Add "Excel 97–Excel 2003", "*.xls"
If .Show = True Then
FilePathToAISCShapesDatabase = .SelectedItems(1)
'Now I have the filepath to the AISC Shapes Database
Else
Exit Sub
End If
End With
' Create textfile in this location:
' Application.ThisWorkbook.Path & "AISCListLoc.txt"
'Open the text file
Open DirFile For Output As #1
'Write some lines of text
Print #1, FilePathToAISCShapesDatabase
'Save & Close Text File
Close #1
End If
Skip:
' Read from file that you have path to
Application.ScreenUpdating = False
Application.Workbooks.Open (FilePathToAISCShapesDatabase)
Dim rng As Range
Set rng = Sheets("Database v14.1").Range("C2:C" & Range("C" & Rows.Count).End(xlUp).row)
Me.Controls(MembSectCurrBox).List = rng.value
ActiveWorkbook.Close False
Application.ScreenUpdating = True
Set rng = Nothing
AppActivate ThisWorkbook.Application
Dim i ' Not sure if I really need to have this here or not;
' I also added it in the UserForm_Initialize(),
' but adding it doesn't seem to help
For i = 1 To Me.Controls.Count
If TypeName(Me.Controls(i - 1)) = "Textbox" Then
Me.Controls(i - 1).TabKeyBehavior = False
End If
Next
End Sub
TextBox8Name(i) is a private variant I used to keep track of how many comboboxes get generated (for limitations of an FEA program down the road).
FilePathToAISCShapesDatabase is a global string (in the module) so the user doesn't always have to point to the AISC shapes spreadsheet after the first time.
I tried not to select anything while in the other workbook, AISC Shapes Database v14.1.xlsm, but maybe I messed up?
Source column contains a string in each cell. There are 4000+ cells. These need to be copied and pasted into a worksheet of the active (one that invoked the macro) workbook. Source workbook should be selected by the user using a search/browse pop-up box.
The below code does something close to my intended goal, but the directory as you see is static which is unacceptable. Maximum flexibility should be had with user choosing the source file manually. Furthermore I want to prevent the file path from becoming obsolete every time folders/files get renamed/shifted. Something tell me Application.GetOpenFilename() should be used, but how to correctly implement it?
Having little experience with the VBA, my attempts to mod this macro failed, so I'm asking for your advice on this matter. Again, the below code works well, but it's not flexible enough to be practical.
Edit: the problem is solved. See the final working code.
'MACRO TO READ-IN EXTERNAL EXCEL FILE FROM WHICH JOB NO.'S ARE EXTRACTED INTO USERFORM
Sub ReadDataFromCloseFile()
'IN CASE OF ERROR SEND TO ERROR FUNCTION
On Error GoTo ErrHandler
'PREVENT OPENED EXCEL SOURCE FILE FROM SHOWING TO USER
Application.ScreenUpdating = False
'OPEN SOURCE EXCEL WORKBOOK IN "READ ONLY MODE"
Dim SrcName As String
Dim src As Workbook
SrcName = Application.GetOpenFilename()
Set src = Workbooks.Open(SrcName, True, True)
'GET THE TOTAL ROWS FROM THE SOURCE WORKBOOK
Dim iTotalRows As Integer
iTotalRows = src.Worksheets("PROJECT LIST").Range("A1:A" & Cells(Rows.Count, "A").End(xlUp).Row).Rows.Count
'COPY DATA FROM SOURCE WORKBOOK -> DESTINATION WORKBOOK
Dim iCnt As Integer '(COUNTER)
For iCnt = 1 To iTotalRows
Worksheets("Test_File_8").Range("B" & (iCnt + 1)).Formula = src.Worksheets("PROJECT LIST").Range("A" & (iCnt + 1)).Formula
Next iCnt
'CLOSE THE SOURCE WORKBOOK FILE
src.Close False 'FALSE = DONT SAVE THE SOURCE FILE
Set src = Nothing 'FLUSH DATA
'ERROR FUNCTION
ErrHandler:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
See my changes below. I added two variables X and strSrc. X is a variant that is used to loop through .SelectedItems and strSrc is that string that ultimately holds the path.
Sub ReadDataFromCloseFile()
'Set variable to hold workbook path and workbook path string
Dim X as Variant
Dim strSrc as String
With Application.FileDialog(msoFileDialogFilePicker)
.InitialFileName = "" ' You can provide a base path here
.Title = "Select file."
.AllowMultiSelect = False
If .Show = -1 Then
For Each X In .SelectedItems
strSrc = X
Exit For
Next X
End If
End With
'IN CASE OF ERROR SEND TO ERROR FUNCTION
'On Error GoTo ErrHandler
'PREVENT OPENED EXCEL SOURCE FILE FROM SHOWING TO USER
Application.ScreenUpdating = False
'OPEN SOURCE EXCEL WORKBOOK IN "READ ONLY MODE"
Dim src As Workbook
Set src = Workbooks.Open(strSrc, True, True)
'GET THE TOTAL ROWS FROM THE SOURCE WORKBOOK
Dim iTotalRows As Integer
iTotalRows = src.Worksheets("PROJECT LIST").Range("A1:A" & src.Worksheets("PROJECT LIST").Cells(Rows.Count, "A").End(xlUp).Row).Rows.Count
'COPY DATA FROM SOURCE WORKBOOK -> DESTINATION WORKBOOK
Dim iCnt As Integer '(COUNTER)
For iCnt = 1 To iTotalRows
src.Worksheets("Test_File_8").Range("B" & (iCnt + 1)).Formula = src.Worksheets("PROJECT LIST").Range("A" & (iCnt + 1)).Formula
Next iCnt
'CLOSE THE SOURCE WORKBOOK FILE
src.Close False 'FALSE = DONT SAVE THE SOURCE FILE
Set src = Nothing 'FLUSH DATA
'ERROR FUNCTION
ErrHandler: Application.EnableEvents = True Application.ScreenUpdating = True End Sub
'MACRO TO READ-IN EXTERNAL EXCEL FILE FROM WHICH JOB NO.'S ARE EXTRACTED INTO USERFORM
I wonder whether someone can help me please.
I wanting to use this solution in a script I'm trying to put together, but I'm a little unsure about how to make a change which needs to be made.
You'll see in the solution that the file type which is opened is a Excel and indeed it's saved as such. But I the files I'd like to open and save are a mixture of .docx and .dat (Used by Dragon software) files.
Could someone possible tell me please is there a way by which I can amend the code so it opens and saves the files in file types other than Excel workbooks.
The reason behind this question because I'm currently using a script which creates a list of files in a Excel spreadsheet from a given folder. For each file that is retrieved there is a hyperlink, which I'd like to add fucntionality to which enables the user to copy the file and save it to a location of their choice.
To help this is the code which I use to create the list of files.
Public Sub ListFilesInFolder(SourceFolder As Scripting.folder, IncludeSubfolders As Boolean)
Dim LastRow As Long
Dim fName As String
On Error Resume Next
For Each FileItem In SourceFolder.Files
' display file properties
Cells(iRow, 3).Formula = iRow - 12
Cells(iRow, 4).Formula = FileItem.Name
Cells(iRow, 5).Formula = FileItem.Path
Cells(iRow, 6).Select
Selection.Hyperlinks.Add Anchor:=Selection, Address:= _
FileItem.Path, TextToDisplay:="Click Here to Open"
iRow = iRow + 1 ' next row number
With ActiveSheet
LastRow = .Cells(.Rows.Count, "C").End(xlUp).Row
LastRow = Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
End With
For Each Cell In Range("C13:F" & LastRow) ''change range accordingly
If Cell.Row Mod 2 = 1 Then ''highlights row 2,4,6 etc|= 0 highlights 1,3,5
Cell.Interior.Color = RGB(232, 232, 232) ''color to preference
Else
Cell.Interior.Color = RGB(141, 180, 226) 'color to preference or remove
End If
Next Cell
Next FileItem
If IncludeSubfolders Then
For Each SubFolder In SourceFolder.SubFolders
ListFilesInFolder SubFolder, True
Next SubFolder
End If
Set FileItem = Nothing
Set SourceFolder = Nothing
Set FSO = Nothing
End Sub
Many thanks and kind regards
Chris
Miguel provided a fantastic solution which on initial testing appeared to work 100%. But as you will see from the comments at the end of the post there were some issues when the user cancelled the operation, so I made another post at this link where the problems were ironed out. Many thanks and kind regards. Chris
The code below shows how to retrieve the extension of a file, define an array with “allowed” extensions, and match the extension of the file to the array.
This is the outline for file manipulation, you'll just need to tailor it to you needs
Dim MinExtensionX
Dim Arr() As Variant
Dim lngLoc As Variant
'Retrieve extension of file
MinExtensionX = Mid(MyFile.Name, InStrRev(MyFile.Name, ".") + 1)
Arr = Array("xls", "xlsx", "docx", "dat") 'define which extensions you want to allow
On Error Resume Next
lngLoc = Application.WorksheetFunction.Match(MinExtensionX, Arr(), 0)
If Not IsEmpty(lngLoc) Then '
'check which kind of extension you are working with and create proper obj manipulation
If MinExtensionX = "docx" then
Set wApp = CreateObject("Word.Application")
wApp.DisplayAlerts = False
Set wDoc = wApp.Documents.Open (Filename:="C:\Documents\SomeWordTemplate.docx", ReadOnly:=True)
'DO STUFF if it's an authorized file. Then Save file.
With wDoc
.ActiveDocument.SaveAs Filename:="C:\Documents\NewWordDocumentFromTemplate.docx"
End With
wApp.DisplayAlerts = True
End if
End If
For files .Dat its a bit more complex, specially if you need to open/process data from the file, but this might help you out.
Edit:
2: Comments added
Hi IRHM,
I think you want something like this:
'Worksheet_FollowHyperlink' is an on click event that occurs every time you click on an Hyperlink within a Worksheet, You can find more here
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
'disable events so the user doesn't see the codes selection
Application.EnableEvents = False
Dim FSO
Dim sFile As String
Dim sDFolder As String
Dim thiswb As Workbook ', wb As Workbook
'Define workbooks so we don't lose scope while selecting sFile(thisworkbook = workbook were the code is located).
Set thiswb = thisworkbook
'Set wb = ActiveWorkbook ' This line was commented out because we no longer need to cope with 2 excel workbooks open at the same time.
'Target.Range.Value is the selection of the Hyperlink Path. Due to the address of the Hyperlink being "" we just assign the value to a
'temporary variable which is not used so the Click on event is still triggers
temp = Target.Range.Value
'Activate the wb, and attribute the File.Path located 1 column left of the Hyperlink/ActiveCell
thiswb.Activate
sFile = Cells(ActiveCell.Row, ActiveCell.Column - 1).Value
'Declare a variable as a FileDialog Object
Dim fldr As FileDialog
'Create a FileDialog object as a File Picker dialog box.
Set fldr = Application.FileDialog(msoFileDialogFolderPicker)
'Allow only single selection on Folders
fldr.AllowMultiSelect = False
'Show Folder picker dialog box to user and wait for user action
fldr.Show
'add the end slash of the path selected in the dialog box for the copy operation
sDFolder = fldr.SelectedItems(1) & "\"
'FSO System object to copy the file
Set FSO = CreateObject("Scripting.FileSystemObject")
' Copy File from (source = sFile), destination , (Overwrite True = replace file with the same name)
FSO.CopyFile (sFile), sDFolder, True
' check if there's multiple excel workbooks open and close workbook that is not needed
' section commented out because the Hyperlinks no longer Open the selected file
' If Not thiswb.Name = wb.Name Then
' wb.Close
' End If
Application.EnableEvents = True
End Sub
The above code Triggers when you click the Hyperlink and it promps a folder selection window.
You just need to paste the code into the Worksheet code. And you should be good to go.