Using VBA code to return a cell to specific row - excel

just starting out with VBA and got stuck on this issue;
I have a resource sheet for people/equipment. The available equipment rows are lower in the sheet than the main work plan. I want to be able to select an item of equipment from the work plan and return it to the available equipment rows. The code below is what I have so far but it's not working. Not sure if it's because I have asked it to select activecell for 2 ranges?
Rng1 is the cell I want to move.
Rng2 is in the same column as Rng1 but lower down (I am trying to reference Rng1 with the same value in Column A to select the correct row).
Hope that all makes sense :)
Public Sub Return_Equipment()
Dim Name1 As String, Name2 As String, NameTemp As String, NameRef As String, Rng1 As Range, Rng2 As Range, Rng3 As Range, StatusVar As Boolean
If IsEmpty(ActiveCell) Then
MsgBox "Please select an item of equipment", vbOKOnly + vbInformation, "Selection Error"
Exit Sub
End If
On Error GoTo errorhandler
Set Rng1 = ActiveCell
Do
NameRef = Intersect(ActiveCell.EntireRow, ActiveCell.CurrentRegion.Columns(1)).Value
If (ActiveCell.Value = NameRef) = False Then
ActiveCell.Offset(1, 0).Select
End If
Loop Until (ActiveCell.Value = NameRef) = True
ActiveCell
Set Rng2 = ActiveCell
Set Rng3 = Application.InputBox("Please select last date for returning", Type:=8)
On Error GoTo 0
StatusVar = False
If IsEmpty(Rng2) Then
StatusVar = True
If WorksheetFunction.CountA(Range(Rng2.Address).Resize(, Range(Rng1.Address & ":" & Rng3.Address).Columns.Count)) <> 0 Then
MsgBox "Not all cells are empty in the destination row! Please start again.", vbCritical + vbOKOnly, "Cell Allocation Error"
Exit Sub
End If
End If
'...
'errorhandler:
'...
End Sub
I'll elaborate a little more regarding what I'm trying to do;
In the picture below I want to return the trailer "Trailer 37U52 L4386 (for trk Ranger)" from cells IV:114 & IW:114 to IV:261 & IW:262 and clear data from IV:114 & IW:114.
I start by selecting IV:114 and running the code. The code sets IV:114 to Rng1. Then it looks at Column A for the corresponding value (in this case A:261) and sets Rng2 as the cell in that row in the Rng1 column (IV:261). The end date is selected using the input box and sets Rng3 as the last column I want this change to be applied to (in the same row as Rng1) In this case I select a cell in column IW.
It is then supposed to relabel cells IV:261 & IW:261 with the values from IV:114 & IW:114 and clear data from IV:114 & IW:114. What I see it doing when I run the code is setting IV:114 & IW:114 to "Temp Value" and then relabeling it back to "Trailer 37U52 L4386 (for trk Ranger)"
Does that help anyone to see what is wrong with my code?
Picture of scenario

According to your description, that one should work.
It is not the cleanest version (you should mention worksheet...)
Public Sub Return_Equipment()
Dim Name1, Name2, NameRef As String
Dim Rng1, Rng2, Rng3 As Range
Dim i, j as Long
If IsEmpty(ActiveCell) Then
MsgBox "Please select an item of equipment", vbOKOnly + vbInformation, _
"Selection Error"
Exit Sub
End If
On Error GoTo errorhandler
Set Rng1 = ActiveCell
Set Rng2 = Cells(1, 1)
j = ActiveSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Row - Rng1.Row
For i = 1 to j
If Rng1.Value = Cells(Rng1.Row + i, 1).Value Then
Set Rng2 = Cells(Rng1.Row + i, 1)
End If
Next
If Rng2 = Cells(1, 1) Then
MsgBox "There is no match"
Exit Sub
End if
Set Rng3 = Application.InputBox("Please select last date for returning", Type:=8)
For i=0 to abs(Rng1.Column - Rng3.Column)
If Rng2.Offset(0, Rng1.Column + i).Value <> "" Then
NameRef = "Fail"
MsgBox "Not all cells are empty in the destination row! _
Please start again.", vbCritical + vbOKOnly, "Cell Allocation Error"
End If
Next
If NameRef <>"Fail" Then
For i=0 to abs(Rng1.Column - Rng3.Column)
Cells(Rng2.Row, Rng1.Column + i).Value = _
Cells(Rng1.Row, Rng1.Column + i).Value
Cells(Rng1.Row, Rng1.Column + i).Value = ""
Next
End If
...
error handler
...
End Sub
Just check on the index "i" that it is working properly, maybe it is one unit short or long. It is difficult to reproduce your sheet to test it.
Hope it helps!

Related

bold cell based on specific value in column J

I already tried using this code and its not working
Sub Bold()
With Sheets("1470")
For Each Cell In Range("J:J")
If Cell.Value = "N/A" Then
Cell.Font.bold = True
End If
Next Cell
End With
End Sub
the output that I want to execute is every cell in column J that contains "N/A" gets bold
I got error
"Type mismatch"
Do not use J:J It will slow your code. Find the last row and then check in that range.
To specifically check for #N/A use CVErr() as shown below.
If you want to check for any error then go with IsError() as mentoned by #PawelCzyz.
Is this what you are trying?
With Sheets("1470")
lrow = .Range("J" & .Rows.Count).End(xlUp).Row
For Each cell In Range("J1:J" & lrow)
If CVErr(cell.Value) = CVErr(xlErrNA) Then
cell.Font.Bold = True
End If
Next cell
End With
This answer is based on the assumption you looking for #N/A errors on your worksheet caused by the same formulas in that column.
Sub Test()
Dim rng1 As Range, rng2 As Range
With ThisWorkbook.Sheets("1470")
Set rng1 = .Range("J1:J" & .Range("J" & .Rows.Count).End(xlUp).Row)
If .Evaluate("=SUM(--ISNA(" & rng1.Address & "))") > 0 Then
Set rng2 = Intersect(rng1, rng1.SpecialCells(xlCellTypeFormulas, xlErrors))
rng2.Font.Bold = True
End If
End With
End Sub

Set two different ranges and execute code

I'd appreciate any help as I have no experience in vba.
What I'm trying to do
is that at the sheet "data" when the selected cell belongs to the rng1 then
the value for example 020318 at the cell changes to take the format 02/03/18.
At the same time in column ED at each cell there is a sum formula.
When this sum is under zero then a msgbox should pop up
for example
Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
Dim rng1 As Range
Dim rng2 As Range
Dim cell As Range
Set rng1 = ThisWorkbook.Sheets("DATA").Range("I3:I1000,O3:O1000,P3:P1000,AE3:AE1000,AF3:AF1000,AH3:AH1000,AI3:AI1000")
Set rng2 = ThisWorkbook.Sheets("DATA").Range("ED3:ED1000")
If Not Intersect(ActiveCell, Range("I3:I1000,O3:O1000,P3:P1000,AE3:AE1000,AF3:AF1000,AH3:AH1000,AI3:AI1000")) Is Nothing Then
For Each cell In rng1
If cell <> "" Then
If Len(cell) = 6 Then
cell.Value = Format(cell.Value, "00/00/00")
End If
End If
Next cell
For Each cell In rng2
If IsNumeric(cell) = True Then
If cell.Value < 0 Then MsgBox "Τhe salary " & Cells(cell.Row, 2).Value & " before ....is " & Cells(cell.Row, 3).Value & " try more", vbCritical, "XXXXX"
End If
Next cell
End Sub
thanks in advance

Copy an entire row from sheet 2 which contains any value from column A on sheet 1, into sheet 3

I would like to be able to copy any row from sheet 2 which contains any value from column a in sheet 1. Copied and pasted into sheet 3.
I found this code online but cell value is specific. I have about 80 values so individually listing them would take to long.
Sub Test()
For Each Cell In Sheets(1).Range("J:J")
If **Cell.Value = "131125"** Then
matchRow = Cell.Row
Rows(matchRow & ":" & matchRow).Select
Selection.Copy
Sheets("Sheet2").Select
ActiveSheet.Rows(matchRow).Select
ActiveSheet.Paste
Sheets("Sheet1").Select
End If
Next
End Sub
How about this:
Option Explicit
Sub CopyThings()
Dim rng As Range
Dim rng1 As Range
Dim ans As Integer
On Error GoTo ISAIDRANGE
Set rng = Application.InputBox("what do you want to copy?", "Select Range", Type:=8)
ans = MsgBox("the whole row?", vbYesNo)
Set rng1 = Application.InputBox("where do you want to paste", "Select Range", Type:=8)
Application.ScreenUpdating = False
rng1.Parent.Activate
Select Case ans
Case Is = vbYes
rng.Rows.EntireRow.Copy rng1.Rows.EntireRow
Case Is = vbNo
rng.Copy rng1
End Select
ISAIDRANGE:
Application.ScreenUpdating = True
If Err.Number = 424 Then ans = MsgBox("that's not a valid range", vbExclamation, "I meant a VALID range")
End Sub

how to iterate over all rows of a excel sheet in VBA

I have this code (This code is in Access VBA which tries to read an excel file and after checking, possibly import it):
Set ExcelApp = CreateObject("Excel.application")
Set Workbook = ExcelApp.Workbooks.Open(FileName)
Set Worksheet = Workbook.Worksheets(1)
now I want to iterate over all rows of the excel worksheet. I want something such as this:
for each row in Worksheet.rows
ProcessARow(row)
next row
where
function ProcessARow(row as ???? )
' process a row
' how Should I define the function
' how can I access each cell in the row
' Is there any way that I can understand how many cell with data exist in the row
end function
My questions:
How to define the for each code that it iterate correctly on all
rows that has data?
How to define ProcessARow properly
How to get the value of each cell in the row.
How to find how many cell with data exist in the row?
Is there any way that I detect what is the data type of each cell?
edit 1
The link solves on problem :
How to define the for each code that it iterate correctly on all rows that has data?
but what about other questions?
For example, how to define ProcessARow correctly?
If you need the values in the Row, you need use the 'Value' Property and after do an cycle to get each value
for each row in Worksheet.rows
Values=row.Value
For each cell in Values
ValueCell=cell
next cell
next row
Unfortunately you questions are very broad however I believe the below sub routine can show you a few ways of achieving what you are after. In regards to what datatype each cell is more involved as it depends what data type you wish to compare it to however I have included some stuff to hopefully help.
sub hopefullyuseful()
dim ws as worksheet
dim rng as Range
dim strlc as string
dim rc as long, i as long
dim lc as long, j as long
dim celltoprocess as range
set ws = activeworkbook.sheets(activesheet.name)
strlc = ws.cells.specialcells(xlcelltypeLastCell).address
set rng = ws.range("A1:" & lc)
rc = rng.rows.count()
debug.print "Number of rows: " & rc
lc = rng.columns.count()
debug.print "Number of columns: " & lc
'
'method 1 looping through the cells'
for i = 1 to rc
for j = 1 to lc
set celltoprocess = ws.cells(i,j)
'this gives you a cell object at the coordinates of (i,j)'
'[PROCESS HERE]'
debug.print celltoprocess.address & " is celltype: " & CellType(celltoprocess)
'here you can do any processing you would like on the individual cell if needed however this is not the best method'
set celltoprocess = nothing
next j
next i
'method 2 looping through the cells using a for each loop'
for each celltoprocess in rng.cells
debug.print celltoprocess.address & " is " & CellType(celltoprocess)
next celltoprocess
'if you just need the data in the cells and not the actual cell objects'
arrOfCellData = rng.value
'to access the data'
for i = lbound(arrOfCellData,1) to ubound(arrOfCellData,1)
'i = row'
for j = lbound(arrOfCellData,2) to ubound(arrOfCellData,2)
'j = columns'
debug.print "TYPE: " & typename(arrOfCellData(i,j)) & " character count:" & len(arrOfCellData(i,j))
next j
next i
set rng=nothing
set celltoprocess = nothing
set ws = nothing
end sub
Function CellType(byref Rng as range) as string
Select Case True
Case IsEmpty(Rng)
CellType = "Blank"
Case WorksheetFunction.IsText(Rng)
CellType = "Text"
Case WorksheetFunction.IsLogical(Rng)
CellType = "Logical"
Case WorksheetFunction.IsErr(Rng)
CellType = "Error"
Case IsDate(Rng)
CellType = "Date"
Case InStr(1, Rng.Text, ":") <> 0
CellType = "Time"
Case IsNumeric(Rng)
CellType = "Value"
End Select
end function
sub processRow(byref rngRow as range)
dim c as range
'it is unclear what you want to do with the row however... if you want
'to do something to cells in the row this is how you access them
'individually
for each c in rngRow.cells
debug.print "Cell " & c.address & " is in Column " & c.column & " and Row " & c.row & " has the value of " & c.value
next c
set c = nothing
set rngRow = nothing
exit sub
if you want your other questions answered you will have to be more specific as to what you are trying to accomplish
While I like the solution offered by #krazynhazy I believe that the following solution might be slightly shorter and closer to what you asked for. Still, I'd use the CellType function offered by Krazynhazy rather than all the Iif I currently have in the below code.
Option Explicit
Sub AllNonEmptyCells()
Dim rngRow As Range
Dim rngCell As Range
Dim wksItem As Worksheet
Set wksItem = ThisWorkbook.Worksheets(1)
On Error GoTo EmptySheet
For Each rngRow In wksItem.Cells.SpecialCells(xlCellTypeConstants).EntireRow.Rows
Call ProcessARow(wksItem, rngRow.Row)
Next rngRow
Exit Sub
EmptySheet:
MsgBox "Sheet is empty." & Chr(10) & "Aborting!"
Exit Sub
End Sub
Sub ProcessARow(wksItem As Worksheet, lngRow As Long)
Dim rngCell As Range
Debug.Print "Cells to process in row " & lngRow & ": " & wksItem.Range(wksItem.Cells(lngRow, 1), wksItem.Cells(lngRow, wksItem.Columns.Count)).SpecialCells(xlCellTypeConstants).Count
For Each rngCell In wksItem.Range(wksItem.Cells(lngRow, 1), wksItem.Cells(lngRow, wksItem.Columns.Count)).SpecialCells(xlCellTypeConstants)
Debug.Print "Row: " & lngRow, _
"Column: " & rngCell.Column, _
"Value: " & rngCell.Value2, _
IIf(Left(rngCell.Formula, 1) = "=", "Formula", IIf(IsDate(rngCell.Value), "Date", IIf(IsNumeric(rngCell.Value2), "Number", "Text")))
Next rngCell
End Sub
Note, that you have to call the sub to call a row must also include the sheet on which a row should be processed.

How to make automatic completing the word

My Friends,
I have two sheets (Sheet1 & Sheet2). in sheet2, Column B all the staff names,
and in the sheet1 there is a form to complete, in Cell C3 of it the name of staff is required to be written. what I want to do is "when I write the initial letters of the employee name, I want Excel to give me option names based on Sheet2, Column B. like when we write in Google anything, Google give options.
thanks in Advance for your help.
another idea is use VBA, I've updated the byundt's code.
It's not possible to show immediately the autofill, but you can type some characters and when you play enter the code check the list and if is one match, autofill the data, otherwise ask user if validate the missing name and add it to the list o delete the last value entered.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cel As Range, match1 As Range, match2 As Range, rg As Range, targ As Range
Set targ = Intersect(Target, Range("C:C")) 'Watch the cells in column C
Set sh = Worksheets("registry") 'the sheet2 where you have the list of names
Set rg = sh.Range("A2", "A" & sh.Range("A1").End(xlDown).Row)
If targ Is Nothing Then Exit Sub
Application.ScreenUpdating = False
Application.EnableEvents = False
On Error GoTo errhandler
For Each cel In targ
If Not IsError(cel) Then
If cel <> "" And cel <> " " And Right(cel, 1) <> Chr(10) Then
Set match1 = Nothing
Set match1 = rg.Find(cel & "*", lookat:=xlWhole, MatchCase:=False)
If Not match1 Is Nothing Then
Set match2 = rg.FindNext(after:=match1)
If match2.Address = match1.Address Then
cel = match1
Else
cel.Activate
Application.SendKeys ("{F2}")
End If
Else 'No matches found. The value will be added of the end of range list
msg = "The value """ & Target & """ is not in list, " & vbCrLf & "do you whant to add this item??"
response = MsgBox(msg, 4, "Update list")
If response = 6 Then
sh.Range("A" & sh.Range("A1").End(xlDown).Row + 1) = Target
Else
Range(Target.Address) = ""
End If
End If
Else
If cel <> "" And Right(cel, 1) = Chr(10) Then cel = Left(cel, Len(cel) - 1)
End If
End If
Next cel
errhandler: Application.EnableEvents = True
On Error GoTo 0
Application.ScreenUpdating = True
End Sub

Resources