Excel Macro cut and paste cells with loop - excel

I'm working with lots of data from a clinical study at the moment. For an analysis in SAS I have to change the the arrangement of the data that is stored in an excel table. This means hours of copy and paste if I'd do it manually, so I tried to write a macro. I spent hours on trying to figure out the code, I came up with a draft, of course it doesn't work since I don't have any backgrounds in VBA, so NO deeper understanding of the syntax. Although the problem is REALLY simple. Here's what I want to do (sry, just a link...since I can't post pictures yet)
http://s7.directupload.net/images/140611/b96dhime.png
First the red arrow: cut the value from the top cell in column mmp1_v1 and paste it to the first cell of column mmp1.
Then the blue one: cut the value from the top cell in column mmp1_v2 and paste it to the second cell from the top in column mmp1.
Same thing with the next red and blue arrow. I have 194 rows in every column, 97 with values, 97 empty ones, so the process should be done within a loop, 97 times. All this for a total of 29 columns.
The code I came up with - which obviously doesn't work - looks like this:
Sub cut_paste()
Dim nr As Integer
For nr = 1 to 195
Range("J&nr&").Select
Selection.Cut
Range("I&nr&").Select
ActiveSheet.Paste
Range("K&nr&").Select
Selection.Cut
nr = nr + 1
Range("I&nr&").Select
ActiveSheet.Paste
Next nr
End Sub
I wanted it to do like in Java kind of. I know...not the same language, but I just thought about defining a count variable called 'nr' and insert it into the string that stands for the range. But I don't understand the error messages, and this is definitely not the only problem. Sry for the missing proper terms...English isn't my mother tongue. I'd be SO glad if someone could try to write an example that kind of works the way I imagined. If you could even follow what I wanted to have.
What I still had to do then would be altering the names of the ranges. Since there are another 29 columns that have to be processed in the same way. But still better than just copy and paste all of this manually I think...
Thanks a lot in advance!

You have to handle strings differently in vba. You also need to lose the nr = nr + 1, as the next will increment it. See code below:
Sub cut_paste()
Dim nr As Integer
For nr = 1 to 195
Range("J" & nr).Select
Selection.Cut
Range("I" & nr).Select
ActiveSheet.Paste
Range("K" & nr).Select
Selection.Cut
Range("I" & nr).Select
ActiveSheet.Paste
Next nr
End Sub

Related

Looping imports through different sheets

I am a newbie to VBA but got tasked to work with it anyway. So my task is to build a macro that takes data from different sheets and puts it below each other in one result sheet ("Tabelle1" in my example). The input data in each sheet is stored in blocks of two columns, right next to each other - so columns A and B have to import into the result sheet, then C and D and so on. Doing this for one sheet is not a problem:
Sub Makro1()
'
' Makro1 Makro
'
Dim Erste As Long
Dim k As Long
Dim j As Long
k = 1
j = 2
Do
Sheets("Tabelle1").Select
Erste = ActiveSheet.Cells(Rows.Count, 3).End(xlUp).Offset(1, 0).Row
Sheets("Tabelle2").Select
Range(Cells(5, k), Cells(5, j)).Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Sheets("Tabelle1").Select
Cells(Erste, 3).Select
ActiveSheet.Paste
k = k + 2
j = j + 2
Loop Until Sheets("Tabelle2").Cells(4, k).Value = ""
End Sub
But I not only have one input sheet ("Tabelle2" in this example) but several (up until sheet20 or so). And all of them are built the exact same way, only with different data in each. What I would need the macro to do is, when reaching the empty cell in the first input sheet ("Tabelle2), go to the next input sheet ("Tabelle3") and continue the import of the data.
It doesn't sound too hard to do at first, but I cannot seem to find a solution. If anyone could help me out, it would be very much appreciated :-)
I know that the macro itself is very badly written and I can get rid of most of the Select. But as long as it works I'm fine.
Instead of using the name of the sheet, use the Index
Example: Sheet(1) and Sheet(2) etc
You can use that number as a variable that you can increment.
Example:
Dim i as Integer
Sheet(i).Select
Note:
It is also better practice to change the code to not rely on .Select as it can cause confusion and problems.
In addition, it would be better to use Worksheet(1) as charts can also be referred to as sheets.

Copy the last 5 cells in a column until last row

I have a text based system with people's names, and I need to copy and paste the first 4 cells (not a problem) and the last 5 cells to a different worksheet for analysis.
The problem arises with the transfer from the text based system the data is presented in, to the spreadsheet when it comes to people with spaces in their surname (ie, Da Silva). I use text to columns, which will give me a variant number columns, depending on the number of spaces in the name which is an issue.
I already have a crude solution, but the time it takes and the jumping about between screens while the macro is running looks very unprofessional. I don't get much spare time at work, and I don't have the tools to test this properly at home.
Can anyone help me get this to loop until the last empty cell, and basically neaten it up a little?
The code, which repeats 300 times, is as following:
Sheets("Late list Sorting").Select
Range("A2").End(xlToRight).Select
Range(ActiveCell.Offset(0, 0), ActiveCell.Offset(0, -5)).Select
Selection.Copy
Sheets("Late list").Select
Range("D4").Select
ActiveSheet.Paste
(...Repeat until...)
Range("A300").End(xlToRight).Select
Range(ActiveCell.Offset(0, 0), ActiveCell.Offset(0, -5)).Select
Selection.Copy
Sheets("Late list").Select
Range("D302").Select
ActiveSheet.Paste
Sheets("Late list Sorting").Select
If you only want the values (not formulae or formatting) then you can simply use Value=Value...
Dim i As Long, sWs As Excel.Worksheet, tWs As Excel.Worksheet
Set sWs = ThisWorkbook.Worksheets("Late list Sorting")
Set tWs = ThisWorkbook.Worksheets("Late list")
For i = 2 To 300
tWs.Range(tWs.Cells(i + 2, 4), tWs.Cells(i + 2, 8)).Value = sWs.Range(sWs.Cells(i, 1).End(xlToRight), sWs.Cells(i, 1).End(xlToRight).Offset(0, -5)).Value
Next
it is inefficient to use .Select, here's a great resource: How to avoid using Select in Excel VBA
To eliminate the screen flashes, put this at the beginning of your code. Remember to turn it back to true at the end.
Application.ScreenUpdating = False
You want to use a loop, where the variable i becomes the row number you will reference like so:
Range("A" & i).Value...
There are many ways to loop, here is one example:
For i = 1 to 300
//All your code here
Next i

How to refactor comparison loops in my excel vba code for speed?

I am new to Excel VBA and do not have much experience. I have two worksheets of data that I compare and then if a value matches up I copy and paste it to the second worksheet. I use for loops to compare every row and was wondering if there is a better way to do this? I am using brute force currently and was hoping there would be a way so that my program will not run for very long. (I repeat this block of code on different sheets 13 times). Essentially this code is consolidating information if it meets certain conditions. Below is my code.
Sub consolidate(z)
Sheets(z).Range("B1:AXH100").Delete '''deletes former values'''
For i = 1 To 30
For x = 1 To 500
If IsEmpty(Sheets("Sheet1").Cells(x, 13)) Then 'if cell value is empty skip it'
a = 1
Else:
If Sheets("Sheet1").Cells(x, 18) = Sheets(z).Cells(1, 1) Then 'check to see if value is same'
If Sheets("Sheet1").Cells(x, 13) = Sheets(z).Cells(i, 1) Then 'check to see if value is same'
Sheets("Sheet1").Cells(x, 15).Copy 'copy value'
Sheets(z).Select 'select second sheet'
Cells(i, 1).Select
ActiveSheet.Cells(ActiveCell.Row, Columns.Count).End(xlToLeft).Offset(0, 1).Select 'offsets cell to the
left'
Selection.PasteSpecial past:=xlPasteValues 'pastes'
End Sub
As I answered here, if you need to access or change several cells, you're much better off reading the cells into an array, working directly with the array(s) and sending the results back to Excel once you're done. It's quite a bit more work, and Excel's array-handling is not the best, but speed-wise there's no comparison.
This article explains the process in more detail.

Delete blank rows using Macro, after Row x

I've found this Macro on another post:
Sub DelBlankRows()
Columns("A:A").Select
Selection.SpecialCells(xlCellTypeBlanks).Select
Selection.EntireRow.Delete
End Sub
Can this be modified so that it only deletes rows after row x (row 14 on the spreadsheet that I'm currently working on)?
Thanks!
this is fairly straightforward.
Rows(x & ":" & y).EntireRow.Delete
Just swap x and y for the rows you want.
As an aside, it is best to avoid selecting ranges unnecessarily as it only slows things down. Any time you select a range then do something with the selection, you can just perform that action directly on the range instead.
EDIT: Just re-read the question - so try this one:
Range("A14:A" & Cells.SpecialCells(xlCellTypeLastCell).Row).SpecialCells(xlCellTypeBlanks).EntireRow.Delete

Macro that adds a sum after inserting a row to a relative position

I am a newbie with excel. It took me days to figure out how to create a button macro that inserts a new row relative to the position of the button. I can currently do this with my macro. However, what I want to do is in that new row that was just created, to pre-populate a sum formula. Please see screenshot for better clarification. http://i.imgur.com/V6dyyXb.jpg
In this specific case, it would create an sum formula in cell C10 of =sum(E10:G10) but I don't want it to specifically go to those points, I need it all to be relative. Can you please help me, I am a complete excel macro noob.
Here is my insert macro:
Sub INSERT_NEW_ROW()
ActiveSheet.Shapes(Application.Caller).TopLeftCell.EntireRow.Select
Selection.INSERT Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
End Sub
I'm not even sure if this is possible, but would be really cool if it is.
Kudos for you to figuring it out this far on your own. Good work! My gut reaction is to use an offset from your button, which it looks like you're using for your relative reference:
Sub INSERT_NEW_ROW()
ActiveSheet.Shapes(Application.Caller).TopLeftCell.EntireRow.Select
Selection.INSERT Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
ActiveSheet.Shapes(Application.Caller).TopLeftCell.Activate
ActiveCell.Offset(-1,1).Formula = "=SUM(E" & ActiveCell.Row - 1 & ":G" & ActiveCell.Row - 1 &")"
End Sub
There are ways to make this more dynamic, but as long as your worksheet has the same format every time, this should work.
What this does is set the top left cell of the area your button covers as a range. Then it fills in a formula in the row above (the -1 in the Offset) and one column to the right (the 1 in the Offset). Since the button is one row greater in the sheet than the one we want to reference, you fill in the formula with ActiveCell.Row - 1 to get the correct row.

Resources