It's been years since I last had to code anything, but now I seem to need it again.
To simplify, I have number 7 in column A, and I need to input another number in column B depending on what number 7 relates to in another table in another sheet.
So in Sheet2 another table has numbers ranging from 1 to 10 in column A, and according numbers in column B. I then need it to search for number 7 in column A of sheet2 and give me the number in column B, and place it in column B in the first sheet.
I have tried a For loop inside a For loop, based on another code I found somewhere, but it's been so long ago I would need to spend hours rereading and trying to get near a solution. Maybe this is an easy thing for advanced coders?
Anyways, thanks in advance for the help!
couldn't you ever help without VBA then you can use this
Option Explicit
Sub main()
Dim cell As Range, f As Range
Dim rng1 As Range, rng2 As Range
Set rng1 = Worksheets("Sht1").Columns(1).SpecialCells(xlCellTypeConstants) '<--Change "Sht1" to your actual sheet1 name
Set rng2 = Worksheets("Sht2").Columns(1).SpecialCells(xlCellTypeConstants) '<--Change "Sht2" to your actual sheet2 name
For Each cell In rng1
Set f = rng2.Find(what:=cell.Value2, LookIn:=xlValues, lookat:=xlWhole, MatchCase:=xlNo)
If Not f Is Nothing Then cell.Offset(, 1) = f.Offset(, 1)
Next cell
End Sub
Here are two ways of doing searching over two tables.
Sub LoopValues()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim wsSource As Worksheet, wsSearch As Worksheet
Dim sourceLastRow As Long, searchLastRow As Long
Dim i As Long, j As Long
Set wsSource = Worksheets("Sheet3")
Set wsSearch = Worksheets("Sheet4")
With wsSource
sourceLastRow = .Range("A" & Rows.Count).End(xlUp).Row
searchLastRow = wsSearch.Range("A" & Rows.Count).End(xlUp).Row
For i = 2 To sourceLastRow
For j = 2 To sourceLastRow
If .Cells(i, 1).Value = wsSearch.Cells(j, 1).Value Then .Cells(i, 2).Value = wsSearch.Cells(j, 2).Value
Next
Next
End With
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Sub FindValuesLoop()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim wsSource As Worksheet, wsSearch As Worksheet
Dim sourceLastRow As Long
Dim i As Long
Dim SearchRange As Range, rFound As Range
Set wsSource = Worksheets("Sheet3")
Set wsSearch = Worksheets("Sheet4")
With wsSource
sourceLastRow = .Range("A" & Rows.Count).End(xlUp).Row
Set SearchRange = wsSearch.Range(wsSearch.Range("A1"), wsSearch.Range("A" & Rows.Count).End(xlUp))
For i = 2 To sourceLastRow
Set rFound = SearchRange.Find(What:=.Cells(i, 1).Value, LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False)
If Not rFound Is Nothing Then .Cells(i, 2).Value = rFound.Offset(0, 1).Value
Next
End With
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Related
I have one column with values like
himaanshu
akshay
rahul
hgeet
And another column with values like
axs,fdvf,dasad
axs,fdvf,dasad, himaanshu
axs,fdvf,dasad, akshay
asz,wesd,hgeet
I need to return the matching name for every row in Column 2 from whole list of Column 1
Solution Should be:
1. None
2. himaanshu
3. akshay
4. hgeet
Can anyone help me with the formula that I can use in spreadsheet to solve this.
Try the below:
Sub test()
Dim str1 As String
Dim rngToSearch As Range, cell As Range
Dim LastRowA As Long, LastrowC As Long, i As Long, y As Long
Dim arr As Variant
With ThisWorkbook.Worksheets("Sheet1")
LastRowA = .Cells(.Rows.Count, "A").End(xlUp).Row
LastrowC = .Cells(.Rows.Count, "C").End(xlUp).Row
Set rngToSearch = .Range("C2:C" & LastrowC)
For i = 2 To LastRowA
str1 = .Range("A" & i).Value
For Each cell In rngToSearch
arr = Split(cell.Value, ",")
For y = LBound(arr) To UBound(arr)
If Trim(arr(y)) = Trim(str1) Then
.Range("B" & i).Value = str1
End If
Next y
Next cell
Next i
End With
End Sub
Results:
See if this formula works (in a google spreadsheet)
=ArrayFormula(iferror(REGEXEXTRACT(C2:C5, textjoin("|", 1, A2:A5)), "none"))
The formula extracts any of the values in column A from the values in column C
[
=VLOOKUP("*"&A1&"*", B1:B4,1,0)
I have Access data I'm trying to export to a Word table. The table has 3 columns, the first row and first column are all headers.
I'm trying to loop through the recordset and populate columns 2 & 3 with data. I'm able to start at row 2 and populate columns 2 and 3, but I cannot figure out how to move to the next row.
iTbl = 1
irow = 2
iCol = 1
Do Until recSet2.EOF
If irow > wDoc.Tables(iTbl).Rows.Count Then
wDoc.Tables(iTbl).Rows.Add
End If
For Each fld In recSet2.Fields
On Error Resume Next
iCol = iCol + 1
wDoc.Tables(iTbl).Cell(irow, iCol).Range.Text = Nz(fld.Value)
Next fld
recSet2.MoveNext
irow = irow + 1
iCol = 1
Loop
The best way to create a table in Word, especially one with a lot of data, is to first write the data into a character-delimited string format. Assign the string to a Range in Word, then use the ConvertToTable method to turn it into a table. That will save a lot of trouble with manipulating the object model and is the most efficient approach (fastest in execution).
The following code demonstrates this principle. The procedure Test creates a new instance of Word, creates a new document in the Word application then assigns the character-delimited string to the document content. This is then turned into a table. If you need to format that table, use the tbl object to do so. The way this code is written requires a reference to the Word object library (early binding). Note that it's also possible to use late-binding - you'll find loads of examples for that.
The second procedure, concatData is called in Test to create the character delimited string. It uses a Tab character as the field separator and a carriage return as the record separator. Word will accept pretty much anything as the field separator; the record separator must be a carriage return (ANSI 13).
Sub Test()
Dim wd As Word.Application
Dim doc As Word.Document
Dim rng As Word.Range
Dim tbl As Word.Table
Set wd = New Word.Application
wd.Visible = True
Set doc = wd.Documents.Add
Set rng = doc.Content
rng.Text = concatData()
Set tbl = rng.ConvertToTable
End Sub
Public Function concatData() As String
Dim retVal As String
Dim rsHeader As Long, rsCounter As Long
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset("nameOfRecordset", dbOpenDynaset)
'Get headers
For rsHeader = 0 To rs.Fields.Count - 1
retVal = retVal & rs.Fields(rsHeader).Name & vbTab
Next
'Replace last TAb with a carriage return
retVal = Left(retVal, Len(retVal) - 1) & vbCr
Do While Not rs.EOF
'Get all records
For rsCounter = 0 To rs.Fields.Count - 1
retVal = retVal & rs.Fields(rsCounter).Value & vbTab
Next
retVal = Left(retVal, Len(retVal) - 1) & vbCr
rs.MoveNext
Loop
concatData = retVal
End Function
Thanks for all the help guys. I managed to figure it out and works very well. It wouldn't move down to the next row and was attempting to write data to column(4) which doesn't exist, then throwing an error. Here is the code I used:
iTbl = 1
iRow = 2
iCol = 1
For Each fld In recSet2.Fields
iCol = iCol + 1
If iCol < 4 Then
wDoc.Tables(iTbl).Cell(iRow, iCol).Range.Text = Nz(fld.value)
Else
If iCol > 3 Then
iCol = iCol - 2
iRow = iRow + 1
wDoc.Tables(iTbl).Cell(iRow, iCol).Range.Text = Nz(fld.value)
End If
End If
Next fld
I have two tables and require the first table to be updated as the third screen shot.
This is the first table. The VON is the first value of the range. This value is picked up from the second table till the BIS value is reached. While the BIS value is reached in the second table, the RANGE column is updated with the values between VON and BIS values.
The second table contains sequentially listed values from 01 to 99 and alphanumeric values such as A1, A2 etc.
Any suggestions?
Try This:
Option Explicit
Sub ExpandRows()
Dim rgLastCell As Range
Dim rgThisRow As Range
Dim wsMaster As Worksheet
Dim wsNewSheet As Worksheet
Dim rgThisRecord As Range
Dim intVon As Integer
Dim intRes As Integer
Dim dblCopyRowNumber As Double
Set wsMaster = ActiveSheet
Set wsNewSheet = Worksheets.Add(after:=wsMaster)
wsNewSheet.Name = "Output"
Set rgLastCell = GetLastCell(wsMaster)
dblCopyRowNumber = 2
wsMaster.Rows(1).Copy wsNewSheet.Range("A1")
wsmaster.columns.autofit
For Each rgThisRow In Range("A2:A" & rgLastCell.Row)
Set rgThisRecord = wsMaster.Range(Cells(rgThisRow.Row, 1).Address, Cells(rgThisRow.Row, rgLastCell.Column).Address)
Debug.Print rgThisRecord.Address
If IsNumeric(rgThisRecord(8)) Then
intVon = rgThisRecord(8).Value
intRes = rgThisRecord(9).Value
While intVon <= intRes
rgThisRecord.Copy wsNewSheet.Range("A" & dblCopyRowNumber)
wsNewSheet.Cells(dblCopyRowNumber, 11).Value = intVon
dblCopyRowNumber = dblCopyRowNumber + 1
intVon = intVon + 1
Wend
Else
rgThisRecord.Copy wsNewSheet.Range("A" & dblCopyRowNumber)
dblCopyRowNumber = dblCopyRowNumber + 1
End If
Next
Set rgLastCell = Nothing
Set rgThisRow = Nothing
Set wsMaster = Nothing
Set wsNewSheet = Nothing
Set rgThisRecord = Nothing
End Sub
and this is the find last cell function:
Function GetLastCell(ByVal wsCurrentSheet As Worksheet) As Range
Dim rgLastRow As Range
Dim rglastColumn As Range
Dim rgLastCell As Range
Set rgLastRow = wsCurrentSheet.Cells.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious)
Set rglastColumn = wsCurrentSheet.Cells.Find("*", searchorder:=xlByColumns, searchdirection:=xlPrevious)
Set GetLastCell = wsCurrentSheet.Cells(rgLastRow.Row, rglastColumn.Column)
Set rgLastCell = Nothing
Set rgLastRow = Nothing
Set rglastColumn = Nothing
End Function
Hope that helps.
I haven't tried coding except in javascript in the past, however i'm pretty new.
I'm trying to create a macro for excel that will compare a the values in sheet1 in column B individually to corresponding column B in sheet2 to find a match. If no match is found the entire row is added to the bottom of the spreadsheet. any help on where to start would be appreciated.
I have 6 columns in the list
The key to what you are attempting is in understanding the nested Loops.
Begin by looping through Sheet 1
Set a temp Value for each row
Begin loop of Sheet 2, each row comparing the temp Value.
Use a boolean variable to track if there was a match or not
At the end of the loop of Sheet 2, If there was no match
Copy the row, by looping through the columns
Continue looping through Sheet 1
Code:
Sub CopyNoMatch()
Dim lastSourceRow As Long
Dim source As String, target As String
Dim tempVal As String
Dim tRow As Long, lRow As Long, lCol As Long, nRow As Long
Dim match As Boolean
source = "Sheet1"
target = "Sheet2"
lastSourceRow = Sheets(source).Range("A" & Rows.count).End(xlUp).row
For lRow = 2 To lastSourceRow 'Loop through Rows on Sheet1
match = False 'Reset boolean test for each new row
tempVal = Sheets(source).Cells(lRow, "B").Text 'Assign the tempValue to compare
For tRow = 2 To lastTargetRow 'Loop through entire target sheet
If Sheets(target).Cells(tRow, "B").Text = tempVal Then
match = True
End If
Next tRow
If match = False Then 'No Match found, copy row
nRow = Sheets(target).Range("A" & Rows.count).End(xlUp).row + 1
For lCol = 1 To 6 'Copy entire row by looping through 6 columns
Sheets(target).Cells(nRow, lCol).Value = Sheets(source).Cells(lRow, lCol).Value
Next lCol
Next lRow
End Sub
I have code that takes fields from a MS Access form and copies the data into a saved Excel file. The first record in Access in imported to Excel with a range of A2:I2. The second record in Access is imported to Excel with a range of A3:I3, and so on.... What currently happens now is if I close my form in Access and open it back up, and say I already had two records imported into this same Excel file, and now I want to add a third record, it will start over at the first row (A2:I2) and write over what is already there. My question is how can I, if I close and open Access keep it from starting over on (A2:I2), and instead start at the next available row, which to follow the example given would be (A4:I4)? This is the code I have
Private Sub Command73_Click()
Set objXLApp = CreateObject("Excel.Application")
Set objXLBook = objXLApp.Workbooks.Open("Y:\123files\Edmond\Hotel Reservation Daily.xls")
objXLApp.Application.Visible = True
With objXLBook.ActiveSheet
Set r = .usedRange
i = r.Rows.Count + 1
.Cells(i + 1, 1).Value = Me.GuestFirstName & " " & GuestLastName
.Cells(i + 1, 2).Value = Me.PhoneNumber
.Cells(i + 1, 3).Value = Me.cboCheckInDate
.Cells(i + 1, 4).Value = Me.cboCheckOutDate
.Cells(i + 1, 5).Value = Me.GuestNo
.Cells(i + 1, 6).Value = Me.RoomType
.Cells(i + 1, 7).Value = Me.RoomNumber
.Cells(i + 1, 8).Value = Date
.Cells(i + 1, 9).Value = Me.Employee
End With
Set r = Nothing
Set objXLBook = Nothing
Set objXLApp = Nothing
End Sub
You can get the last used row:
Set r = objXLBook.ActiveSheet.UsedRange
i = r.Rows.Count + 1
Some notes.
Private Sub Command73_Click()
''It is always a good idea to put sensible names on command buttons.
''It may not seem like much of a problem today, but it will get there
Dim objXLApp As Object
Dim objXLBook As Object
Dim r As Object
Dim i As Integer
''It is nearly always best to check whether Excel is open before
''opening another copy.
Set objXLApp = CreateObject("Excel.Application")
Set objXLBook = objXLApp.Workbooks.Open( _
"Y:\123files\Edmond\Hotel Reservation Daily.xls")
objXLApp.Application.Visible = True
''It is generally best to specify the sheet
''With objXLBook.ActiveSheet
With objXLBook.Sheets("Room Reservation")
''If the used range includes empty rows
''it may not suit
''Set r = .UsedRange
''i = r.Rows.Count + 1
''From comments, it appears that the data is dense
''but with a number of empty rows at the end of the sheet
i = .Range("A1").End(xlDown).Row + 1
.Cells(i, 1).Value = Me.GuestFirstName & " " & GuestLastName
.Cells(i, 2).Value = Me.PhoneNumber
.Cells(i, 3).Value = Me.cboCheckInDate
.Cells(i, 4).Value = Me.cboCheckOutDate
.Cells(i, 5).Value = Me.GuestNo
.Cells(i, 6).Value = Me.RoomType
.Cells(i, 7).Value = Me.RoomNumber
.Cells(i, 8).Value = Date
.Cells(i, 9).Value = Me.Employee
End With
''Tidy up
Set objXLBook = Nothing
Set objXLApp = Nothing
End Sub
You might also like to look at TransferSpreadsheet.
Another possibility is to use the RecordsetClone, for data from a form, or any recordset, for that matter. It does not give quite the same control, but it is very fast:
Dim objXLApp As Object
Dim objXLBook As Object
Dim r As Object
Dim i As Integer
Dim rs As DAO.Recordset
Set objXLApp = CreateObject("Excel.Application")
objXLApp.Visible = True
Set objXLBook = objXLApp.Workbooks.Open( _
"Y:\123files\Edmond\Hotel Reservation Daily.xls")
Set rs = Me.RecordsetClone
With objXLBook.Sheets("Sheet1")
Set r = .UsedRange
i = r.Rows.Count + 1
.Cells(i, 1).CopyFromRecordset rs
End With