Excel VBA - How to insert values only? - excel

I'm looking for a way to copy a range (copyrange exists from 11 columns and a variety of rows) from an other workbook and insert/paste values only in my primary workbook, underneath the data already there.
Just pasting is no issue, but because I don't want it to overwrite the last (SUM-)line I want to INSERT the values. By my knowing there isn't anything like InsertSpecial xlInsertValues.
So how can I insert entire empty rows based on the counted rows of the copied range and than paste the values only in columns "E" to "O"?
Some preconditions are:
copyrange exist from 11 columns and a variety of rows
I'm trying to avoid having to switch twice between the two documents. So I only want to open the extern workbook, copy the values, open my primary workbook en insert the copied data with blank cells left and right from the range.
This is what I've got so far. It all goes wrong at the Insert part, because it doesn't paste/insert values only. Note that it's only a part of a bigger code. Rng31 is the copied range in the extern workbook.
Dim Rng31 As Range
Set Rng31 = Rng21.Resize(Rng21.Rows.Count, Rng21.Columns.Count + 10)
Dim regels As Integer
regels = Rng31.Rows.Count
Rng31.Copy
Wbbase.Activate
Sheets(2).Activate
Dim onderste As Range
Set onderste = Range("E65536").End(xlUp).Offset(1, 0)
onderste.Insert shift:=xlDown
Selection.PasteSpecial xlPasteValues

...
InsertValues Rng21.Resize(Rng21.Rows.Count, Rng21.Columns.Count + 10), _
Wbbase.Sheets(2).Range("E65536").End(xlUp).Offset(1, 0)
...
Sub InsertValues(rngCopyFrom As Range, rngCopyTo As Range)
Dim rngDest As Range
Set rngDest = rngCopyTo.Resize(rngCopyFrom.Rows.Count, _
rngCopyFrom.Columns.Count)
Application.CutCopyMode = False 'Edit Added:clear any copied data
rngDest.Insert shift:=xlDown
rngDest.Offset(-rngCopyFrom.Rows.Count).Value = rngCopyFrom.Value
End Sub

The problem is that if you have a cell copied (i.e. its on the clipboard) you cannot simply "insert a new row" because the only option is to "insert copied cells" thus the onderste.Insert will insert the copied cell and keep the formula. In addition you then call Selection.PasteSpecial which I do not think is what you desired because you never set your selection anywhere in your code post, so whatever you had selected prior is what will contain the value.
You have a couple options:
You can insert the row first, then copy and paste the cell value (this requires toggling back and forth between workbooks)
Copy the cell, insert the new row (which is what you are doing) then clear the row and paste in the values.
As a side note:
Range("E65536").End(xlUp).Offset(1, 0)
would be better stated as
Range("E" & Rows.Count).End(xlUp).Offset(1, 0)

Related

Return cells content from range

Yesterday I learned here how to copy a row to a second sheet.
Sub maJolieProcedure(Texte As String)
With Worksheets("employes").Range("A:A")
Set c = .Find(what:=Texte)
If Not c Is Nothing Then
firstAddress = c.Row
Worksheets("employes").Rows(firstAddress).Copy _
Destination:=Worksheets("rapport").Range("A1")
MsgBox "Ok"
Else
MsgBox "Nok"
End If
End With
End Sub
To respect the formatting of the second sheet, I want to copy and paste the contents of each cell one by one.
I can identify the line number. However, I can't figure out how the Range object can return each cell one by one. For example, C3 content if Rows = 3.
Thanks a lot.
If you don't want to paste the formatting from one range to another paste values only.
Worksheets("employes").Rows(firstAddress).Copy
Worksheets("rapport").Range("A1").PasteSpecial xlValues
That's the same for all ranges, whether 1 cell or a million. The Copy process copies the subject to memory as one block. Any parsing must be done before the Copy instruction. An alternative is to read a range into an array.
Dim Arr As Variant
Arr = Worksheets("employes").Rows(firstAddress).Value
This will create a 3D array of 1 row and about 16000 columns. You might decide to limit your enthusiasm to only what you need.
With Worksheets("employees")
Arr = .Range(.Cells(firstAddress, 1), .Cells(firstAddress, .Columns.Count).End)xlToLeft)).Value
End With
Pay attention to the leading periods within the With statement. Each such period stands for the object mentioned in the With statement.
If your goal is to respect the formating of the second sheet, you don't need to loose time copying cell by cell.
It is more effective to do a paste special, like you do with the mouse:
Range("A1").Copy
Range("B1").PasteSpecial Paste:=xlPasteValues
works very well also with bigger ranges if you need:
Range("A1:A12").Copy
Range("B1:B12").PasteSpecial Paste:=xlPasteValues
or even
Range("A1:A12").Copy
Range("D3").PasteSpecial Paste:=xlPasteValues
If your goal is to really access all cell of a range individually , you just iterate on the range. For example:
For Each cell In Range("A1:A12")
cell.Value = cell.Value + 2
Next cell

Find cell & select/copy from active cell to last row including blanks

I'm attempting to find a column using the column header name, then select all the data from the column (including the blank cells) & paste into another range.
Currently I can only copy until the 1st blank cell. I have seen similar problems on the board but the solutions I have seen are coming from the angle of knowing which column it is in first & then finding the last row from the bottom of the worksheet.
Workbooks("PS & Config - Actuals & FC.xlsm").Worksheets(2).Range("A3").CurrentRegion.Find(What:="FFA Name").Select
Range(ActiveCell, ActiveCell.End(xlDown)).Select
Range("A3").Select
ActiveSheet.Paste
To find the column use Match wit the column header name. Once you have that column, set the values in the destination range to be the same as that column. Selecting, copying, and pasting in VBA are unnecessary as the values themselves can be moved--plus it adds load.
I don't have Office anymore so I'm running this from memory. I hope it helps.
dim wb as workbook, ws1, ws2 as worksheet, myCol, myRow as long
set wb=excel.thisworkbook 'assuming this code goes in that workbook
set ws1=wb.sheets(2) 'set variables
myCol=worksheetfunction.match("FFA Name",ws1.[a1:zz1],0) 'search through 1st row
myRow=ws1.[a3].currentregion.rows.count 'grab last row containing data in this set
'do not select, nor copy and paste, if it can all be done with VBA. This can.
set ws2=wb.sheets.add 'a little rusty on this line, you can get the method from the macro recorder
ws2.cells(1,1).resize(myrow).value=ws1.cells(1,myCol).resize(myrow).value
The reason your original code stops when there's a blank cell is because the .end() method simulates pushing the end key and then an arrow, which goes to the first/last contiguous cell with data.
Range(ActiveCell, ActiveCell.End(xlDown)).Select

VBA to reference the same cell even after the addition or deletion of rows & Columns

I'm using VBA code to write to cells in excel. For eg.
Range("C3") = code
Or
Cells(3,3) = code
If a row is inserted in the sheet, the code does then not update accordingly and would still write to Range("C3") etc. So the code then writes to the incorrect cell.
Is there a better way I can structure my code so it will update accordingly? Perhaps using a table instead of cells?
One solution is to used Named Ranges. You can define a Named Range in Formula Tab by clicking on Name Manager.
Then you will write.
Range("Name of the Range") = code
My believe is that named ranges update automatically when a row or column is inserted, so your code will print the value in the correct cell.
Thanks, good idea. I ended up defining the column filled with values as a range, then use a for loop to search for the defined string. That way it doesnt matter what row it is in aslong as the name and string doesnt change (Using a Named Range will probably be better for that exact reason).
Worksheets("Sheet1").Select
Set WS = ActiveSheet
With WS
LastRow = .Cells(.Rows.Count, 2).End(xlUp).Row 'Determine the last row number with data in it for column B
For Each acell In .Range("B1:B" & LastRow) 'Defines the search range from B1 to last row
If acell.Value = "String Searched For" Then
'Do stuff based on found cell location
End If
If acell.Value = "String Searched For#2" Then
'Do stuff based on found cell location#2
End If
Next
End With

Copying values from one Table to the first empty row in another Table

As part of my project I have a Table which includes lookup formulas in each column that are dragged down the whole table. Depending on the case only the first x rows return values. I included an iferror so that the lookups that don't return values return "".
Now I want to copy the rows of the table that return values to the first empty row in a different table in a different worksheet.
The code I have so far:
Sub Copy_Results()
Application.ScreenUpdating = False
Dim copySheet As Worksheet
Dim pasteSheet As Worksheet
Set copySheet = Worksheets("Sheet1")
Set pasteSheet = Worksheets("Sheet2")
copySheet.Range("Table1").Copy
pasteSheet.ListObjects("Table2").Range.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub
Now the big problem is that I want to be able to execute this macro multiple times, each time the values from Table 1 should be pasted below the preexisting values in table 2.
The point being that each time the lookup values change meaning I get new results I want to paste them in a table where all the results are documented.
Issues that I had so far:
The first Copy Paste usually works, but when I copy again the values get pasted way below the first ones outside of the table. Usually the full length of the table away. I guess this is because the whole copy table is filled with formulas.
The easiest way to do this is to restrict the cells that you are going to copy using the SpecialCells method:
https://msdn.microsoft.com/en-us/library/office/ff196157.aspx
In this case you only want to copy the formulas that have numbers as the values, so this would be the syntax:
SpecialCells(xlCellTypeFormulas, xlNumbers)
Put into your code it would be:
copySheet.Range("Table1").SpecialCells(xlCellTypeFormulas, xlNumbers).Copy
You can see this in action outside of your code by selecting the complete range in your source sheet then pressing F5, selecting the "Special" button at the bottom of the dialog that pops up, then select "Formulas" and "Numbers".
To make sure it pastes in the next available row, use the CurrentRegion property:
https://msdn.microsoft.com/en-us/library/office/ff196678.aspx?f=255&MSPPError=-2147217396
This code will tell you what the last row is in the used area defined by cell A1:
pasteSheet.cells(1,1).CurrentRegion.Rows.Count
I believe the paste command you're looking for will be close to this (hard to test exactly without your spreadsheet):
pasteSheet.cells(pasteSheet.cells(1,1).CurrentRegion.Rows.Count + 1, 1).PasteSpecial xlPasteValues

Copy value-only cells in multiple worksheet columns and paste into one column

I have multiple spreadsheets that I need to copy column starting at "S4", on a specifically named worksheet, and I need only the cells in that column (starting at S4 and everything below it) that contain data.
I need to copy that data and paste it into my "main" spreadsheet starting at A2 on a specific worksheet. I can do this with one spreadsheet, but the problem I'm running into I need VBA to find the last cell in column A that has a value and start pasting new data into the cell below it, etc... Otherwise, when it's looking at the other spreadsheets, it's just overwriting the data in my main spreadsheet.
You'll notice the specified range of S4:S2000 - its purpose was for a single spreadsheet, which worked fine because I never had data past 2000, but I really just need it looking for cell values and grabbing those.
This is the chunk of code where I'm having the trouble. I want it to search starting at A2 (skipping the column header), look for the last cell that has a value and paste cells with values starting at S4 on the other worksheet.
On Error Resume Next
Set wbkCS = Workbooks.Open(strCutSheetFile(i))
On Error GoTo 0
If Not wbkCS Is Nothing Then
With wbkVer.Sheets("Cutsheets")
.Range(.Cells(2,1)).End(xlUp).Row = wbkCS.Worksheets("Cut Sheet").Range("S4:S2000").Value
I had to tweak yours a little because I'm working with protected files, but this worked:
Set copyRng1 = Worksheets("Cutsheets").Range("A2")
If copyRng1 = "" Then
wbkCS.Worksheets("Cut Sheet").Range("S4:S2000").Locked = False
wbkCS.Worksheets("Cut Sheet").Range("S4:S2000").Copy Destination:=wbkVer.Worksheets("Cutsheets").Range("A2")
Else
wbkCS.Worksheets("Cut Sheet").Range("S4:S2000").Copy Destination:=wbkVer.Worksheets("Cutsheets").Range("A" & wbkVer.Worksheets("Cutsheets").Range("A65536").End(xlUp).Row + 1)
End If
Here's an example that may push you in the right direction...
Suppose I want to aggregate my data in Sheet1 using data from S4:S2000 in all other worksheets in the workbook.
Sub CopyAndStack()
Dim wkShtIndex As Integer, copyRng As Range
Set copyRng = Worksheets(1).Range("A2")
For wkShtIndex = 2 To Worksheets.Count
If copyRng = "" Then
Worksheets(wkShtIndex).Range("S4:S2000").Copy Destination:=copyRng
Else
Worksheets(wkShtIndex).Range("S4:S2000").Copy Destination:=Range("A" & copyRng.End(xlDown).Row + 1)
End If
Next wkShtIndex
End Sub
I check if A2 is empty and if so I paste the first lot of data.
If A2 is not empty I get the next empty cell in column A and paste it there.
Here's how you can get exactly the rows that are populated in S:
Dim StrRange As String
. . .
'Get range
strRange = "S4:S" & Worksheets(wkShtIndex).UsedRange.Columns("S:S").Rows.Count
'Do something with range
Worksheets(wkShtIndex).Range(strRange)

Resources