excel: correct column position - vba

Actually, it is a simple question, although I don't know if it's possibl to do what I wanted to.
I'm just copying a column from another using this sub:
Sub copy_column()
Sheets("FROM").Columns("A").Copy Destination:=Sheets("TO").Columns("A")
End Sub
In fact, in my sheet "FROM" my first row with data is the row 3 and then when I copy to "TO" sheet it's starting from row 3 too. My idea was to place it at the row 1 at "TO" sheet.
Is there any way to write something like Columns("A"-2) to put it in the right place?

An alternative which avoids deleting rows (if you have data you want to keep in other columns for example) is to take an intersection of a range overlaid with itself, but offset...
The following code assumes you have some data in row 1 in the sheet so UsedRange would start from the correct row, but you can change the offset to accommodate missing data in the rows above
Dim CopyRange As Range
With Sheets("From")
Set CopyRange = Application.Intersect(.UsedRange, .Columns("A"))
Set CopyRange = Application.Intersect(CopyRange, CopyRange.Offset(2, 0))
CopyRange.Copy Destination:=Sheets("TO").Cells(1, 1)
End With

Related

Excel VBA - Extract Multiple Values from a Single Cell and Associate Values in Source Cell's Row

To preface this, I have very little experience in Excel VBA, but have used some VBA in Access.
I have a file which may contain multiple values in a single cell that need to be extracted out onto individual rows, and then have the data in multiple columns from the source row re-associated with the extracted values.
The multiple values in the single cell that need to be extracted are always in a uniform format. The cell may contain any number of sets of (), but the value I need to extract is always between the 2nd : and the closing ). This is the 'Identifier'.
For example:
(00050008009:STC:363711188)(00040022506:NYC:652263975)
Would need to extract these values onto individual rows:
363711188
652263975
All remaining values from the Source Row the value was extracted from then need to be re-associated with the value.
For example, my file may look like this:
Original File Format
I then need the file to appear as follows, on a new tab:
New File Format
I believe that a module making use of a loop, or multiple loops, is likely what is needed, but I have no idea of how to go about doing this in Excel. I'm open to all solutions. Any help is greatly appreciated! Thank you!
Without writing it for you, here are some pointers to get you started.
You'll need to loop through each cell in the column that contains the information you're looking for. For this, look into Worksheet.Range.
As you go through each cell, you'll need to examine the data that is actually entered into that cell. Using the Worksheet.Range.Value you can extract the contents of the cell.
Use excels string functions to parse the cell value into the values your looking for. Ex: InStr, InStrRev, etc... See this link for your options and usage for each function.
Finally you'll need to insert a row for each value that you find. Lookup Worksheet.Rows.Insert.
This should be the basic framework for what you need to do.
you may want to start with this code:
Option Explicit
Sub main()
Dim myArr As Variant
Dim cell As Range
Dim iRow As Long, nArr As Long
With Worksheets("batches").Range("A1").CurrentRegion '<--| change "batches" with your actual sheet name
For iRow = .Rows.Count To 2 Step -1 '<--|loop through data rows backwards, not to process rows multiple times
Set cell = .Cells(iRow, 3) '<--| 3rd column of current row is being processed
cell = Mid(cell, 2, Len(cell) - 2) '<--|get the cell value between first and last bracket
myArr = Split(cell, ")(") '<--|parse the resulting string with ")(" as delimiter and obtain and array
nArr = UBound(myArr) '<--| calculate the array size
If nArr > 0 Then '<--| if more than one element in array...
With .Rows(iRow) '<--|... then refer to entire current row
.Offset(1).Resize(nArr).Insert '<--| ...insert n-1 rows...
.Resize(nArr + 1).Value = .Value '<--|...duplicate current row into newly inserted ones
End With
cell.Resize(nArr + 1).Value = Application.Transpose(myArr) '<--|fill 3rd column of current and newly inserted rows with array elements
End If
Next iRow
For iRow = 2 To .Rows.Count '<--|loop through data rows
With .Cells(iRow, 3) '<--| 3rd column of current is being processed
.Value = Right(.Value, Len(.Value) - InStrRev(.Value, ":")) '<--| "finish" it
End With
Next iRow
End With
End Sub
As per your example, it assumes that your data start from cell "A1" and there's no blank row or column between it and the bottom-right cell of your data

Copy row from one sheet and insert copied row under last row in another sheet

I am in need of your expert assistance.
I am trying to write some code that will copy rows and insert the copied row below the last row in another sheet.
I have a Global sheet that has the data i will be copying. It will need to look in column Q.
I think the problem will be when trying to copy the data, the data in column G is the text name of a Contract Code. But the sheets are name with the Number version.
for example i have a row that has BRREPAIRS in column Q, I need this to copy to Sheet 2870, then i have a row that has BRVOIDS in column Q, I need this to copy to Sheet 2781.
I could have multiple different Contract names so i think i might need to define the text to equal a sheet. So maybe Set BRVOIDS = Sheet.name("2781") Set BRREPAIRS = Sheet.name("2780") and so on until all sheets are defined.
When the data gets copied i need it to find the last row in column a that has data, when it is found it will insert the copied row into the sheet. for example EntireRow.Insert Shift:=xlDown.
I dont have any code at the moment. I would really appreciate all the assistance.
You don't need to do things like Set BRVOIDS = Sheet.name("2781"). In fact, that would be positively harmful since then you would need to run the data in Column Q through a possibly large Select statement to know what variable to use. Instead, you could write a function like
Function TargetSheet(ContractName As String) As Worksheet
'code which uses your secret list to determine target sheet
'Maybe a Select statement, Maybe a Vlookup -- who knows?
Set TargetSheet = 'sheet your code determined
End Function
Sounds like your code will be scanning down column Q, determining where to copy the corresponding row to. Once you get the above function working, you could combine it with something like this:
Function LastRow(TargetCol As Variant, Optional ws As Variant) As Range
'assumes TargetCol is something like 1 or "A"
Dim n As Long
If IsMissing(ws) Then Set ws = ActiveSheet
n = ws.Cells(1, TargetCol).EntireColumn.Rows.Count
Set LastRow = ws.Cells(n, TargetCol).End(xlUp).EntireRow
End Function
This returns as a range the last row containing data (or row 1 if the column is empty) in a specified column in a specified worksheet (which defaults to the Active sheet).
You haven't given enough to go on, but something along the lines of
LastRow("A",TargetSheet(Range("Q" & i).Value)).Insert Shift := xlDown
Might be what you are looking for. Why don't you try to work it out and ask another question (if need be) once you have some actual code?

Removing a row in a table if it doesn't contain keyword

Right now I have a really long table in a Word doc which I populated from an Excel worksheet. It has 6 columns and I'm trying to code something in Word VBA that will go through all the rows in the table and delete the entire row if the cell in the first column DOES NOT start with an equal sign ("=").
For example, I'm only trying to keep the rows that has texts like,
"=1+S -03F7", "=1+M -06M1", etc. etc.
How would I code this? I can't give the code anything specific to look for since the parts after the equal sign will be different for every row.
So this wouldn't work, right?:
If Not ActiveDocument.Tables(83).Columns(1).Range.Text = "=" Then
EntireRow.Select
Selection.Delete
I guess I should reference to cells in column 1, not the column itself... Also, it doesn't work because it's only looking for things with just the equal sign... And I don't know how I can get it to select the row if it find the cell without the equal sign. I don't know how to match by case in the cell of the first column.
You can loop through the rows in the table using the Rows property. You can then find the first cell in that Row using the Cells property. You can then check just the first character of the Range:
Sub DeleteUnwantedRows()
Dim t As Table
Dim r As Row
Set t = ActiveDocument.Tables(1)
For Each r In t.Rows
If r.Cells(1).Range.Characters(1) <> "=" Then r.Delete
Next r
End Sub

Best way to return data from multiple columns into one row?

I have a sheet with just order numbers and another with order numbers and all of the data associated with those order numbers. I want to match the order numbers and transfer all of the available data into the other sheet. I've been trying to use loops and VLOOKUP but I'm having problems (plus I have 116 columns I want to transfer data from so my vlookup expression doesn't look very nice). Any advice would be appreciated!
this is what I have so far and I'm getting an object error.
I don't think it's the right way to go about it in general though.
Dim LookUpRange As Range
Dim row As Range
Set LookUpRange = Worksheets("batches").Range("B4:B1384")
Set row = Worksheets("batches").Range("C:DL")
For Each row In LookUpRange
row.Select
Selection.FormulaArray ="=VLOOKUP(RC[-1],OrderLvl!RC[-1]:R[1380]C[113],{2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,207,108,109,110,111,112,113,114,115},FALSE)"
Next row
End Sub
Please consider this VBA script to resolve your inquiry:
Sub LookupOuput()
Dim OrderNumberColumn As Range
Set OrderNumberColumn = Worksheets("batches").Range("B2:B1384")
Dim LookUpRange As Range
Set LookUpRange = Worksheets("OrderLvl").Range("C:DL")
Dim cell As Range
Dim FindResult As Range
For Each cell In OrderNumberColumn
If Not cell.Value2 = Empty Then
Set FindResult = LookUpRange.Find(what:=cell.Value2)
If Not FindResult Is Nothing Then
cell.Range("A1:DJ1").Value2 = LookUpRange.Rows(FindResult.row).Value2
End If
End If
Next cell
End Sub
Basically searches for each Order Number in the first sheet on the second sheet. This outputs (if search term exists) the cell that that string is found which we later refer to its row number to output the whole row to the first sheet. Cheers,
A regular VLOOKUP may be able to give you what you need, if you use a small trick...
Insert a row above the data table, and put sequential numbers in
each cell of that row. (ie, A1 = 1, B1 = 2, C1 = 3, etc...)
Do the same thing on your blank table.
Assuming that your first order number is in cell A2, put the following formula into B2: =VLOOKUP($A2,[other sheet name]!$A$1:$DZ$5000,B$1,0)
Drag this formula across all 116 columns, then down all however many rows you've got.
You'll need to adjust the ranges, obviously, but make sure that your lookup array starts in column A. (or alternatively, that your numbers start in the same column as the first column in your array.) Adding the numbers along the top allows you to change what column of the array you're referencing, just by dragging the cell formula.

Excel: Use values in a sheet as index to list in a different sheet and replace values in the first sheet

I have an XL file with some data to be manipulated. I think I will need to use a VB script to do this - but perhaps there is a simpler way with a formula. Just the same, could someone point out BOTH ways of achieving the following?
I have a column of numeric values (ID) in Sheet 1.
I want to use each ID as an index to lookup a list in Sheet 2.
Sheet 2 has two columns
First column is the index and Second column is the Text String
e.g.
1 Apple
2 Orange
3 Pear
What I want is to replace the column of IDs in sheet 1 with the looked up text string from Sheet 2!
Thats all...
Please help!
Not a tough situation there. Here are some solutions...
With VBA:
I know you said you're a little new with VB so I tried to explain each line as I went along. Also, the code is free-handed so forgive me if I left an error in there somewhere.
Sub replaceData()
dim i as integer, j as integer 'These are just some variables we'll use later.
dim sheetOne as worksheet, sheetTwo as worksheet, myWb as workbook
dim myData as string, myId as string
set myWB = excel.activeworkbook 'These three lines set your workbook/sheet variables.
set sheetOne = myWB.worksheets("Old Data")
set sheetTwo = myWB.worksheets("New Data")
for i = 1 to sheetTwo.usedrange.rows.count 'This loops through the rows on your second sheet.
myId = sheetTwo.cells(i,1).value 'This assigns the value for your id and the data on your second sheet.
myData = sheetTwo.cells(i,2).value
for j = 1 to sheetOne.usedrange.rows.count 'This loops through the rows on your first sheet.
if sheetOne.cells(j,1).value = myId then 'This checks each row for a matching id value.
sheetOne.cells(j,1).value = myData 'This replaces that id with the data we got from the second sheet.
end if
next j
next i
end sub
With an Excel formula:
Place the following formula in cell C1 of the first worksheet (the
sheet with the IDs you will be replacing). **Note that you will
have to replace the "InsertSheetTwoNameHere" portion with the name
of your second sheet (don't remove those single quotes though). Also
note you will need to replace the "1000" with the number of the last
used row in sheet two.
=vlookup(A1,’InsertSheetTwoNameHere’!$A$1:$B$1000,2,FALSE)
Next simply drag the handle on the cell that makes it copy itself
(whatever the heck it's called) all the way down to the end of your
range.
Next, copy those cells and then paste them over the IDs using the
Values Only setting.
Hope this helps and good luck.