I have code that creates pivot tables then populates another workbook with data. It opens a workbook that acts as a template for the data, populates it, saves and closes. It does this 8 times for 8 different sets of data. I've run this code many times before without issue and seemingly now it starts to error out with: "Cannot change part of a data table" on the second set of data (the first one works). The section that it is erroring out on is...
'Transfers Repairs Data
Range("D27").Select
ActiveCell.FormulaR1C1 = _
"=VLOOKUP(RC[-1],'[VBA Project.xlsm]Repairs Pivot'!R5C8:R60C11,4,FALSE)"
Selection.AutoFill Destination:=Range("D27:D30"), Type:=xlFillDefault
Range("D27:D30").Select
Range("D85").Select
ActiveCell.FormulaR1C1 = _
"=VLOOKUP(RC[-1],'[VBA Project.xlsm]Repairs Pivot'!R5C8:R60C11,4,FALSE)"
Any idea whats causing this?
Not really an answer but an improvement to help you.
'Transfers Repairs Data
Range("D27:D30").FormulaR1C1 = _
"=VLOOKUP(RC[-1],'[VBA Project.xlsm]Repairs Pivot'!R5C8:R60C11,4,FALSE)"
Range("D85").FormulaR1C1 = _
"=VLOOKUP(RC[-1],'[VBA Project.xlsm]Repairs Pivot'!R5C8:R60C11,4,FALSE)"
Also be sure you're on the right sheet and as others commented that there's no data table where you're trying to paste these formulas. To use a particular sheet you can alter the above:
Sheets("Sheet1").Range("D27:D30").FormulaR1C1
Related
Original Post: Here (New post as it started to get very clunky and dragged away from the issues at hand)
I am looking to automatically grab data from an excel CRM output and take certain values into a new sheet. I have had a bit of luck with my progress, but I am still struggling to adapt the code properly.
First Iteration of Code:
Sub Client_CRM()
Range("A4:A44,C4:C44,G4:H44").Select
Selection.Copy
Sheets("Output Sheet").Select
Range("A1").Select
ActiveSheet.Paste
End Sub
Current code:
Sub Client_CRM()
Dim ClientStartRow As Long, ClientEndRow As Long
Dim Listed As Long
Set PortfolioRange = Worksheets("Client Paste").Range("A:M")
Set Listed = Worksheets("Client Paste").Range("A:A")
With Sheets("Client Paste")
Sheets("Output Sheet").Cells.Clear
Worksheets("Client Paste").Activate
ClientStartRow = .Range("A3").Row
':A").Find(What:="Listed", after:=.Range("A1")).Row
ClientEndRow = .Range("A:A").Find(What:="Totals", after:=.Range("A3"), LookIn:=xlValues, lookat:=xlPart, MatchCase:=False).Row
Range(ClientStartRow & ":" & ClientEndRow).Select
Selection.Columns(1).Copy
Sheets("Output Sheet").Select
Range("A3").Select
ActiveSheet.Paste
Sheets("Output Sheet").Range("B1:B70") = Application.VLookup(Listed, PortfolioRange, 8, False)
Sheets("Output Sheet").Range("C1:C70") = Application.VLookup(Listed, PortfolioRange, 3, False)
Sheets("Output Sheet").Range("D1:D70") = Application.VLookup(Listed, PortfolioRange, 7, False)
End With
End Sub
As you can see, I've slowly added and learnt more things throughout today.
What I am now looking to do is:
Find a better way to copy the columns over to the new sheet. **An issue that I have encountered is that maybe 1/10 CRM exports have an additional column, so the VLOOKUP can't accurately be used 100% - The CRM export has headers. Can I use some sort of code to grab these columns by value? They are exported and on Row 2. "Listed" "Quantity" "MV" "PW" are the 4 headings. Usually they are columns: 1,3,7,8 but in a rare instance they are 1,3,8,9...
Find a way to remove certain "blacklist" products. All products generally have a 3 part code that they are identified as. There are certain 3 part codes I do not want included and I want to be able to update this as time goes on. Ideally, I'd like to make a separate sheet with these codes and if they match to anything from the export, they aren't copied over...
Some product codes have 5 characters instead of 3, I'd like these ones to be coped in the same list but added to a separate list (Unsure if this is possible?)
Update:
Have worked out how to get the code to bring the 4 columns I want regardless of their order over.
Set PPSExport = Range("A2:M2")
For Each cell In PPSExport
If cell.Value = "Asset" Then
cell.EntireColumn.Copy
ActiveSheet.Paste Destination:=Worksheets("Output Sheet").Range("A:A")
End If
If cell.Value = "Quantity" Then
cell.EntireColumn.Copy
ActiveSheet.Paste Destination:=Worksheets("Output Sheet").Range("B:B")
End If
If cell.Value = "Market value" Then
cell.EntireColumn.Copy
ActiveSheet.Paste Destination:=Worksheets("Output Sheet").Range("C:C")
End If
If cell.Value = "Portfolio weight %" Then
cell.EntireColumn.Copy
ActiveSheet.Paste Destination:=Worksheets("Output Sheet").Range("D:D")
End If
Next cell
Sheets("Output Sheet").Select
End With
Thanks for any help,
I've already learnt so much already -- any pointers would be greatly appreciated :D
Yes, all of these things are possible. I will give a brief description on how to accomplish all of these things, but I recommend that you try to research how to do each of these tasks on your own before asking another question(s). It's also a good idea to keep the scope of your question limited. For example, you are asking about 3 loosely related items here. Yes, they are related to one another via your project, but in the general world of VBA programming, they are not. This will keep the conversation focused and easier to follow.
Find a better way to copy the columns over to the new sheet.
You made a great observation: your data is imported with headers. And your proposal is possible. You can certainly use the headers of a range (or table) to copy data. You could:
Iterate through all cells in the header row
If you come across one you are interested it, copy all of the data in that column to the new sheet
If you come across a column header you are not interested in, just skip it and move to the next one
Find a way to remove certain "blacklist" products.
This is possible, and your proposed solution sounds ideal to me. Keep a record of all blacklist values in a sheet, and reference that list when necessary.
Some product codes have 5 characters instead of 3, I'd like these ones
to be coped in the same list but added to a separate list
Certainly possible. Once you have your data:
Iterate through all of it and check how many characters are in the value
If there are 5, copy that data to a new location or store it somewhere
If there are not 5, move on to the next value
Basically I made a macro which does a few copy-paste, and change the filter on the pivot table. Now, there are quite a few pivots, with the same filter to be changed (a date), so I want to make a variable for them.
So the macro works without variables, but when I put:
Dim x,y as Date
x = "2020/9/1"
y = 2020/8/20"
And then put it into the pivot name -I cant copy the full code, nor the parts, because they are on virtual deskop for work.
Activesheet.PivotTables("pivottable3").PivotSelect "'2020/9/1' text" _
xlDataAndLabel, True
and I changed this to:
Activesheet.PivotTables("pivottable3").PivotSelect "'x' text" _
xlDataAndLabel, True
and I get an error saying this name doesn't exist. What did I do wrong?
Greets,
I got this scenario with 3x different files;
1) one CSV file has Column A (-first row) with abbreviations that needs to be copied on XLSX file (also in Column A)
+
2) another CSV has many rows and column where is explanation for the first case (abbrevations), and I have to look for explanation inside that big file (so vlookup I used).
=
3) xlsx file is separate that has to combine both CSV into one, where on Column A I will have abbreviations and on Column B explanations of the certain terms.
I tried with functions and simply defining ranges:
Column A1 ='C:\Users\MirzaV\Desktop\1\[0528-matrix.csv]0528-matrix'!A3
Column B1 =VLOOKUP(A1;'C:\Users\MirzaV\Desktop\1\[variantendb.csv]variantendb'!$C:$D;2;0)
So seems nothing hard or else, but problem is I am having XXX of these CSV files and one main CSV file with explanations (it is stated as "varianten") , that are gonna be updated periodically - all of the files.
Instead to open three files at the same time just to refresh my functions, is it a bit quicker way with a code or other functions?? And I would like to have it in XLSX file.
I tried to record a macro but it didnt work good, I was thinking I can use it for rest of the files but always gives an error.
Application.Left = 2318.5
Application.Top = 89.5
Windows("0528-matrix1.xlsx").Activate
Range("A1").Select
ActiveCell.FormulaR1C1 = "='0528-matrix.csv'!R[1]C"
Range("A1").Select
Selection.AutoFill Destination:=Range("A1:A500"), Type:=xlFillDefault
Range("A1:A500").Select
ActiveWindow.Close
ActiveWindow.ScrollRow = 1
Application.Left = 2161
Application.Top = 1
Application.Width = 720
Application.Height = 780
Windows("0528-matrix1.xlsx").Activate
Range("B1").Select
ActiveCell.FormulaR1C1 = "=VLOOKUP(RC[-1],variantendb.csv!C3:C4,2,0)"
Range("B1").Select
Selection.AutoFill Destination:=Range("B1:B500")
Range("B1:B500").Select
Application.Left = 1896.25
Application.Top = 32.5
Application.Width = 864
Application.Height = 493.5
Windows("variantendb.xlsx").Activate
ActiveWindow.Close
Application.Left = 1669
Application.Top = 1
ChDir "C:\Users\MirzaV\Desktop\1"
Since you're using Office 365 we can use the Get & Transform feature to create links to your CSV files. As long as you maintain the same filenames on the CSVs, this will enable Excel to automatically update the data.
We'll complete this data merge in 3 stages:
Link the reference CSV (the second file you have listed) to a table
Link to the data CSV (the first file) to a table
Write an Index/Match function to pull the descriptions.
Stage 1: Linking the reference file to a table
In a new Excel workbook, click on the Data tab, then click on the New Query dropdown in the Get & Transform section. Mouse over "From File >" and select "From CSV"
Navigate to CSV 2 and click Import
On the next window that pops up, click "Load"
Your lookup data will now load into a table on a new sheet. Now let's clean up the references here:
Click on the Formulas tab, then Click on Name Manager
Select your new table (it will be named the same as your file)
Change the name to "Reference" and click Ok.
Go to your table and change the column names from "Column 1" and "Column 2" to "Abbr" and "Desc"
And that's it for stage 1! Now that we have the reference table set up and linked, we can move on to loading the data table we want to find the descriptions for.
Stage 2: Linking the data file to a table
We're going to link to the data file in the same way we did the reference file. Go to Data > Get & Transform > New Query > From File > From CSV. Select your file and click Import, then click Load.
On the new table, rename Column 1 to "Code" (I would use Abbr, but Code will help keep the next step looking clear).
Add another column to this table. The simplest way is to just click in B1, type "Desc" (or whatever name of your choosing) and hit Enter.
Stage 3: The Index function that makes the magic
On your new data table with the blank description column, click in the first data cell.
Type in the function =INDEX(Reference[Desc],MATCH([#Code],Reference[Abbr],0)) and press Enter.
Watch the magic happen as Excel copies our formula to every cell in that table column!
By setting up our CSV files as external connections in this manner, we're able to create a dynamic table that will always update with the CSVs.
By using Index/Match, we're able to get away from the constraints of VLookup (data in left-most field, sorted alphabetically), and move to a system that allows us to look for the value we need from any field in any order.
Breaking it down, Index returns the value of the cell provided in the target row and column of the specified array or table. Because we specified the target array as a single column of data, we can use Index([array], [row number]), or using the code above Index(Reference[Desc], [row number]). What really makes this work is the use of Match. Match returns the row number in an array of a target value, so we use MATCH([#Code],Reference[Abbr],0). This returns the row number to Index, which then pulls the data from the desired cell.
There are some additional steps we can do using the Power Query Editor to ensure the column headers always stay the same, but that's a tutorial for a different day. Hope this helps!
This has been asked already, but none of the answers available helps me. I am trying to add a row to a small worksheet. I am allowed to add the row with Alt-I, R manually, but if I try to do it from a macro, I get this:
I have tried, without effect, the following suggestions I have found on the Internet:
Check that data isn’t ridiculously long. Ctrl-End takes me to G40. The last available row is 1048576.
Unfreeze panes.
Execute “ActiveSheet.UsedRange” in the Immediate window.
Unmerge cells in row above the one I was inserting.
Rows("1048500:1048576").Delete. This ought to free up 76 rows, yet immediately after it attempting to insert just one row is forbidden.
Application.CutCopyMode = False
Selecting all the rows below those used and choosing “Clear Content”, save, close and reopen.
I am using Excel 2016. The only solution that looks at all plausible is using Application.SendKeys to do Alt-I, R, but I would rather not do that if I can help it. Neither the sheet nor the workbook containing it is protected. If you want to know what the offending code is:
For iWorksheetCounter = 2 To wbkFinal.Worksheets.Count
Set wksPartial = wbkFinal.Worksheets(iWorksheetCounter)
lngCurrentRow = iWorksheetCounter + iRowOffset ' iRowOffset = 3
wksTotals.Rows.Insert (lngCurrentRow + 1) ' this is not allowed for a reason I don't understand
wksTotals.Cells(lngCurrentRow, 1).Value = wksPartial.Name
Next ' iWorksheetCounter
I'm grabbing data from SAP to paste into my Excel sheet via VBA. (There are other methods for exporting data, but this is the one I am limited to.)
The data is put into the Windows-Clipboard via SAP. Afterwards it is put into the newest Excel-Worksheet (see Sub importStuff and then formatted see Sub divData) The data is delimited with pipes | and after pasting it looks like this (including the blanks):
| FOO: BAR | 360.000 |
After I Call divData it is split into two separate columns. (this how I want it to be formatted)
[SOME_ID: SOME_NAME][360.000]
Sometimes Excel formats 360.000 to 360,000 = 360. This only happens for values that end in a 0. So 360.000 is formatted to 360, 312.312.001.800 would be formatted to 312.312.001,80.
I'm using a German version of Excel 14.0.7166.5000 (32-Bit). So a . is for digit grouping, a , is the decimal mark.
This my code
Sub importStuff()
dBegin = wsUeb.Range("BeginPlan")
dEnd = wsUeb.Range("EndPlan")
'lots
'of
'other
'SAP-Stuff
SAP_Session.findById("wnd[0]/usr/tabsTABSTRIP_MYTAB/tabpPUSH4/ssub%_SUBSCREEN_MYTAB:ZCO_SUSAETZE_NEW:0400/ctxtP_LAYOUT").Text = "/ZL_UMSPIEXP"
SAP_Session.findById("wnd[0]/tbar[1]/btn[8]").press
SAP_Session.findById("wnd[0]/tbar[1]/btn[45]").press
SAP_Session.findById("wnd[1]/usr/subSUBSCREEN_STEPLOOP:SAPLSPO5:0150/sub:SAPLSPO5:0150/radSPOPLI-SELFLAG[4,0]").Select
SAP_Session.findById("wnd[1]/tbar[0]/btn[0]").press
ActiveWorkbook.Sheets.Add After:=Worksheets(Worksheets.Count)
Worksheets(Worksheets.Count).Paste
Worksheets(Worksheets.Count).Name = "Plan-Umsaetze " & dBegin & " - " & dEnd
Call divData
End Sub
Sub divData()
ActiveSheet.Columns("A:A").TextToColumns _
DataType:=xlDelimited, _
TextQualifier:=xlTextQualifierNone, _
ConsecutiveDelimiter:=False, _
Other:=True, _
OtherChar:="|"
End Sub
Here is what happens.
I open the workbook
I call importStuff
I call divData afterwards, doesn't matter if it is called within importStuff or not
everything is fine
I call importStuff again
I don't call divData at all (doesn't matter if I do)
I get erroneous values
But if I just press Ctrl+v the values get inserted just fine (see 4.)).
I can't call Ctrl+v via Windows Shell, because the new worksheet is invisible for the user.
This is just Jochen's and my comment posted as an answer. I had the same issue today, that's why I necro'd this post.
I formatted the column to text, imported the data, changed the format back to numbers and then multiplied each value with 1. That did the trick.
you could set Range.numberFormat
or use Range.PasteSpecial( [xlPasteTypes], [xlPasteOperation]), doc here, particularly xlPasteValuesAndNumberFormats or xlPasteSpecialOperationMultiply
I have the same issue but I can solve it by:
range("A1").PasteSpecial(-4142)
it seems like excel sees "---------" as calculation.