VBA Import Data - vba

I have a problem and I think it's complicated. It's regarding importing data/information from a another Excel file and the data/information needed is on 2 sheets.
The code is working but not the way It should be it doesn't seem to import the data and down below it will explain what we cannot do in it, ("me and my friend that are working in this project that was demand by our company don't know almost nothing about this category VBA and we are just researching info about this but get always stuck").
We need to extract from the file (the link is in the description), and the file is created every week(semana) so somehow it needs to extract the newest every week.
Down below there's the Excel file that is responsible for the extraction of the data for security reason we deleted most of the information on it and changed names.
Workbook with the Macro - Used for importing The sheet is the number 2 and also It's called Dev.Pag the macro is associated to the button "IMPORT DATA" in the same file.
Source Workbook - Contains the data This is where it gets the values(exports) from once again the name and some data was erased because It might compromise the company.
If there's anything I can edited or change please tell me. Thanks in advance for any reply.
Also will post the code down below:
Option Explicit
Sub ImportData()
Application.ScreenUpdating = False
Dim Path As String, Lstrw As Long
Dim SourceWb As Workbook
Dim TargetWb As Workbook
'Change this to your company workbook path
Path = "C:\Users\DZPH8SH\Desktop\Status 496 800 semana 12 2015.xls"
Workbooks.Open (Path)
'Change "Source" to the name of your company workbook
Set SourceWb = Workbooks("Status 496 800 semana 12 2015.xls")
'Part that needs some adjustments in down below
'This part is working good but probably some error in the data
'transferance may be intrefering with the integridty
'change the file address
Set TargetWb = Workbooks("Master_Atual_2015.xlsm")
Lstrw = SourceWb.Sheets(1).Cells.Find(What:="*", SearchOrder:=xlRows, _
SearchDirection:=xlPrevious, LookIn:=xlValues).Row
With SourceWb.Sheets(1)
.Application.Union(.Range("D2:D" & Lstrw), .Range("F2:F" & _
Lstrw), .Range("I2:I" & Lstrw), .Range("M2:M" & Lstrw)).Copy _
Destination:=TargetWb.Sheets(1).Range("A3")
End With
SourceWb.Close savechanges:=False
Application.ScreenUpdating = True
End Sub

It was pretty hard to understand your code for several reasons:
You just reference the sheets by index. Thus they are hard to find. Better reference them by name
you reference ranges only by addresses, it would be better to define named ranges
Another point to make it more readable/ debuggable, set the union to an own range object to be able to watch the content and be sure that this is what you want to have.
With SourceWb.Sheets(1)
Set objTargetRange = .Application.Union(.Range("D2:D" & Lstrw), .Range("F2:F" & Lstrw), .Range("I2:I" & Lstrw), .Range("M2:M" & Lstrw))
objTargetRange.Copy Destination:=TargetWb.Sheets(1).Range("A3")
End With
When printing out the objTargetRange's addresses it looks like this (You can do that by simply pressing ctrl+g and writing ?objTargetRange.Address)
$D$2:$D$9;$F$2:$F$9;$I$2:$I$9;$M$2:$M$9
So you selected four columns, each of them has 8 cells. When adding this to A3, it will be added side by side, it doesn't have any offset.
So cells A3-D10 will be overwritten by your data, the code works. It was not visible that it does that, because comparing state before and state after was pretty complicated. You can make visible, that the changes actually happen by just
temporary removing your actual data from the sheet
temporary adding some empty rows

Related

VBA Lookup in Another Workbook

I am having an vba problem with Excel. So I have this workbook, "Book Tool - Updated Feb. 2017.xlsb", that I am currently updating and will distribute to about 10 team members to use to keep track of their work. What I am trying to do is lookup data from an outside document, "Team Data", put that in Column DE of the "Book Tool - Updated Feb. 2017.xlsb" file. So I wrote the below code, where when the team member pushes a button, it opens up the lookup file, looks for the data in Column A of the "SICcode" sheet of that external file, matches it with Column B of the "Book Sheet" of the "Book Tool" file, and returns the value in Column D of the lookup file. It runs for the length of the "Book Sheet", closes the external file, and you get a popup that the data add is done.
Now when I did this code myself, it works great. Automatically opened the external document, did the lookups, returned the correct value, closes the external document, the pop up. So I sent the file with the macro to my manager to play around with before giving it to the rest of my team, but the macro does not work. When the macro runs, the external document opens, it seems like it is running through the lookups, closes the external file, and the pop up appears, but there is no value in the DE column, nor is there the lookup formula there. My manager didn't change the name of the Tool document, he didn't mess with any code. He emailed it back to me and with that copy the formula isn't working, but I checked it with my master copy formula and even though it's the same, the macro will not populate the data.
We have to keep the external data in a separate file, because otherwise the tool with the lookup data is over 2MB and takes forever to run or crashes.
Is there something about emailing the tool back and forth that messes with the file, or is there some formatting issue I need to look into that causes it not to work? With my master copy on my computer, the code always works regardless if I work in a virtual desktop, have it in a different folder, whatever.
I am just okay with vba, I don't know all of the technicalities of this process, so maybe I am overlooking some flaw with how I've set it up or limitations Excel has. Any guidance or help would be appreciated.
Sub AddData()
On Error Resume Next
'Open External Data Source
Workbooks.Open Filename:= _
"W:\USB\Reporting\Book Tool\Attachments\Team Data.xls"
'View sheet where data will go into
Windows("Book Tool - Updated Feb. 2017.xlsb").Activate
'Gets last row of Tool sheet
Sheets("Book").Select
lastrow = Cells(Rows.Count, "B").End(xlUp).Row
'Lookup in External File
Sheets("Book").Select
Range("DE2:DE" & lastrow).FormulaR1C1 = "=VLOOKUP(RC[-108],'[Team Data.xls]SICcode'!C[-109]:C[-104],5,FALSE)"
'Close External Data File
Windows("Team Data.xls").Activate
ThisWorkbook.Saved = True
Application.DisplayAlerts = False
ActiveWindow.Close
MsgBox "Data Add Done"
End Sub
Be sure to properly qualify your statements, and also it would be wise to assign the appropriate workbook to a variable. See the modified code below:
Sub AddData()
On Error Resume Next ' I also suggest removing this since it wont warn you on an error.
Dim wb as Workbook
Dim wbExternal as Workbook
Dim ws as Worksheet
Dim wsExternal as Worksheet
'Open External Data Source
Set wbExternal = Workbooks.Open Filename:= _
"W:\USB\Reporting\Book Tool\Attachments\Team Data.xls"
' Depending on the location of your file, you may run into issues with workbook.Open
' If this does become an issue, I tend to use Workbook.FollowHyperlink()
'View sheet where data will go into
' Windows("Book Tool - Updated Feb. 2017.xlsb").Activate
' Set wb = ActiveWorkbook
' As noted by Shai Rado, do this instead:
Se wb = Workbooks("Book Tool - Updated Feb. 2017.xlsb")
' Or if the workbook running the code is book tool
' Set wb = ThisWorkbook
'Gets last row of Tool sheet
Set ws = wb.Sheets("Book")
lastrow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
'Lookup in External File
Set wsExternal = wbExternal.Sheets("Book")
wsExternal.Range("DE2:DE" & lastrow).FormulaR1C1 = "=VLOOKUP(RC[-108],'[Team Data.xls]SICcode'!C[-109]:C[-104],5,FALSE)"
'Close External Data File
ThisWorkbook.Saved = True
Application.DisplayAlerts = False
Windows("Team Data.xls").Close
MsgBox "Data Add Done"
End Sub
I would also recommend browsing through SO for tips on avoiding .Select and .Activate as this can make your code unreliable and in some cases can slow down your code significantly.
Lastly, if performance is a concern you may want to look into loading your lookup values into arrays and finding the corresponding values this way. It will completely depend on what kind of data you are working with. I had a workbook using filldown vlookups that went from running in a matter of 5-10 minutes or more to consistently running in less than 20 seconds by replacing VLOOKUPS with for looping arrays.

Copy/Paste variable dataset between workbooks without clipboard

I've been trying to optimize some of my coding and managed to cut and speed it up a lot. However there are some things that are still quite clunky (and me still a noob). Backstory is that my code is opening source and target files, copies a lot of data of variable length, closes source and then does a lot of operations and finally saves target file.
One of the things Id like is to do if possible is a direct copy of data without using clipboard, activating workbooks, selecting sheets (whatever of this is possible to pack into more efficient code that I am currently having)
Windows("SOURCE.xlsm").Activate
Sheets("Data").Select
Range("A2:AX10").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Windows("TARGET.xlsm").Activate
Range("A2").Select
ActiveSheet.Paste
Application.CutCopyMode = False
Is it possible to do a selection (A2:AX10 and all the way down to last row) in SOURCE file-Data sheet and directly copy it to TARGET file-Data sheet cell A2 without using clipboard.
The reason why I use A2:AX10 and then selection down is because I have a lot of blank cells in the whole data set and this way I get entire data.
I would like to be able to to that selection and use it as a range in this line
Workbooks(“SOURCE”).Worksheets("Data").Range(“A2:AX10 & ALLTHEWAYDOWN”).Copy _Workbooks(“TARGET”).Worksheets("Data").Range(“A2")
I was trying to solve this but I dont end up with desired result. When I try doing selection and setting as range then both trying copy range with activitng workbooks and in the direct copy mode I get 1004 error.
Is it possible to optimize this chunk and make it work. It would improve a lot of my VBA.
Thanks,
You need something like this:
With Workbooks("SOURCE.xlsm").Sheets("Data")
.Range("A2:AX10", .Range("A2:AX10").End(xlDown)).Copy Workbooks("TARGET.xlsm").ActiveSheet.Range("A2")
End With
You could probably also use CurrentRegion rather than End(xlDown
You can set one range's values (the range where you would want to paste values) equal to a source range's values (the range which you would previously have copied).
Sub paste_values()
Dim wb_A As Workbook, ws_A As Worksheet
Dim wb_B As Workbook, ws_B As Worksheet
Dim last_row As Long
Set wb_A = ThisWorkbook
Set ws_A = wb_A.Sheets(1)
Set wb_B = Workbooks("WorkbookB")
Set ws_B = wb_B.Sheets(1)
With ws_A
last_row = .Range("A" & .Rows.Count).End(xlUp).Row
End With
ws_B.Range("A2:AX" & last_row).Value = ws_A.Range("A2:AX" & last_row).Value
End Sub
This code is setting the new range's values equal to the original range. It prevents the need to activate sheets or workbooks, whilst also copying data to a range without filling the clipboard.
I would also recommend using last_row = .Range("A" & .Rows.Count).End(xlUp).Row to find the last row of your data. Although you do need to ensure you use this on a column which you know contains continuous data.

Run Time error 1004: Select Method of Worksheet class failed with (varCellContent.Parent.Name)

The code edits, then copies data from a temporary sheet to the current workbook. I am using varCellContent to ask the user to choose the source sheet. I had no trouble when testing the code as I was building it by using F8 to step through (and the code still works perfectly like this).
But when I run the macro normally, I am getting
Run Time error 1004: Select Method of Worksheet class failed
on the following line:
Workbooks(varCellContent.Parent.Name).Worksheets("Sheet1").Select
The following may not be relevant to the cause of the problem but I have read a bit about it while searching for an answer.
It sounds like using .Select is not a good idea, but there are 2 reasons I thought it was useful in this situation.
I don't have to name the sheet for each of the following rows of code that delete and move the columns.
When building and debugging the code I wanted the sheet to be visible so that I could see what was happening as I stepped through each line of code.
So taking those 2 reasons into account is there still a better way to avoid using .Select?
Sub ImportNewData()
'
'
' Import data, save as new workbook
Dim LR As Long
LR = Range("A" & Rows.Count).End(xlUp).Row
' Clear data
Range("A3:I" & LR).ClearContents
' User choose source sheet
Dim varCellContent As Worksheet
Set varCellContent = Application.InputBox _
(prompt:=" " & vbNewLine & "Click any cell in the Aged AP Summary that has been exported from Systematic to Excel, then click OK", Type:=8).Parent
Workbooks(varCellContent.Parent.Name).Worksheets("Sheet1").Select
'Delete unrequired columns
Columns("E:I").Select
Selection.Delete Shift:=xlToLeft
Worksheets("Sheet1").Activate
Columns("E:I").Delete Shift:=xlToLeft

Copying row from a sheet to another on clicking a button getting an error

After Clicking on a button some rows are copying from a sheet to another but I am getting an error:
This workbook contains links to one or more external sources that could be unsafe.
If you trust the links,update them to get the latest data. Otherwise, you can keep working with the data you have.
[Update] [Don't Update] [Help]
I have tried clicking Update & Don't Update but it is not copying the data in either manner.
I am putting the value from a cell to wbLocationPath :
Set wbLocationPath = WSheet.Range("A2")
While wbLocationPath.Value <> ""
If IsWorkBookOpen(wbLocationPath.Value) Then
For Each wks In Workbooks
If (wks.Path & "\" & wks.Name) = wbLocationPath Then
Set wb = wks
Exit For
End If
Next wks
Else
Set wb = Application.Workbooks.Open(wbLocationPath.Value, ReadOnly:=False)
End If
so during debugging I got the error on setting the wb value.
wbLocationPath.value is having the path what is in A2 as c\users\me\desktop\project\XYZ.xlsx.
IsWorkBookOpen(wbLocationPath.Value) is returning false so control comes on else part which gives error.
I don't have any problem in pasting the value . My code is working fine for other thousands of filepath but it's not working just for some filepath .
I have some folders, I copied the every file's data from every folder. Getting the problem in a specific folder's("FOOD ADD") some specific files.
As I have some file name like "10024125 (01-0RD)" so all these type of file's datails copying but where the filename is "10016818 (03-1RD) FOOD ADD" is not copying & through the error what I have mentioned.
If you have the workbook open and it comes from a trusted location (see Excel Options ► Trust Center ► Trust Center Settings ► Trusted Locations), then you should not have a problem using a Paste Special, Values since you are only concerned with the values, not the original formulas. However, a direct value transfer may be sufficient to bypass the warnings. There are also some implicit cell parent worksheet references that should be made explicit.
with tmpSheet
lastrow = .Cells(Rows.Count, "A").End(xlUp).Row
Set rng = .Range(.Cells(1, 1), .Cells(lastrow, 1)) '<~~ note all parts belong to tmpSheet
end with
with pasteSheet
For Each c In rng.Cells
If c = "ABC" Then
'the following is an alternative method of direct value transfer
.Cells(Rows.Count, "A").End(xlUp).Offset(1).Resize(1, columns.count) = _
c.Resize(1, columns.count).Value
End If
Next c
end with
Note that when you were defining rng. the parent worksheet was explicit for the .Range but not the .Cells that made up the range. Also, the direct value transfer is a more efficient method of getting the values across without the clipboard.
I strongly suspect that the IsWorkBookOpen is not expecting the full path and workbook name that you are sending it. If it was only expecting the Workbook.Name property then you are never going to get a match when you send it the Workbook.FullName property.
Function IsWorkBookOpen2(sWS As String)
Dim b As Long
For b = 1 To Workbooks.Count
'Debug.Print Workbooks(b).FullName
If lcase(Workbooks(b).FullName) = lcase(sWS) Then _
Exit For
Next b
IsWorkBookOpen2 = CBool(b <= Workbooks.Count)
End Function
This replacement routine performs a non-case-sensitive comparison on the full path and filename (aka Workbook.FullName property) of the open workbooks to the value which you have stored in WSheet.Range("A2").
Note that it is called IsWorkBookOpen2 and not IsWorkBookOpen.
Actually there is no problem in VBA code. The problem is in the excel file . The excel was "linked WorkSheet" i.e it was linked to any server to update the value in excel whenever you want to open. So You can change the Link properties from "Data" menu by selecting "EditLink".
there we can change the prompt properties on the basis of your requirement.
please see the following solution from MS support to suppress the message:
https://support.microsoft.com/en-us/kb/826921

Calling an existing worksheet with vba by using its code name in excel

I am trying to set the formula of a cell to an if formula that uses data from an already existing sheet within the workbook. However whenever trying to reference the sheet i get a file dialog box that opens looking for the path for the sheet. Below you will find my code which loops through all existing sheets in the workbook and compares it to a sheet name when it finds a match it stores the sheet code name for the current and previous weeks. Once it has these I have an if statement that tries to access these sheets and compare values. It is at this point that I get the file dialog box. Any thoughts or suggestions would be greatly appreciated. Thank you. Sorry for formatting issues I will correct as soon as possible.
sheetName = CStr(Year(Now)) & " eDR FW" & CStr(Format(Date, "ww")) & "_2"
lastWeekName = CStr(Year(Now)) & " eDR FW" & CStr(Format(Date, "ww") - 1) & "_2"
For Each ws In ActiveWorkbook.Worksheets
If ws.Name = sheetName Then
sheetName = ws.CodeName
ElseIf ws.Name = lastWeekName Then
lastWeekName = ws.CodeName
End If
Next
rowRange = colLetter & "2:" & colLetter & CStr(sheetRowCount)
lineofBalance = "=IFERROR(IF(INDEX('" & lastWeekName & "'!$A$2:$W$10000,MATCH(A2,'" & sheetName & "'!$A$2:$A$10000,0),6)=F2,F2,CONCATENATE(""Updated: ""&F2)),CONCATENATE(""New: ""&F2))"
All you need to do to make this work is change both ws.Codename to ws.Name.
The .Codename property only contains the first name of the sheet when it was originally created (which is most likely something like "Sheet32") and not the current name of the worksheet. It CAN be changed but most likely will remain the same unless you REALLY intend to change it. The formula with the erroneous worksheet name then opens the dialog box to try to find a reference for that particular worksheet.
Excel's formulas are designed to work with the current worksheet name and not it's codename. The only useful way I can see of using the .Codename, is if you wanna make sure to always use a particular worksheet (within VBA) even if the name of the worksheet was changed at some point (by yourself or a user).