I've been working with some code that opens a workbook and finds values based off a reference cell. It searches for a string and takes the cell next to it. unfortunately i now have 2 cells in the workbook that 'contain' the reference string. one cells is "Current Score" the other is "Percentage of Current Score". Is there a way to state that I just want "Current Score" and nothing else in the cell.
Sorry if this is a tad wordy, I can provide the code if necessary
EDIT: Here is the code:
Sub Future_Score()
Dim r
Dim findValues() As String
Dim Wrbk As Workbook
Dim This As Workbook
Dim sht As Worksheet
Dim i
Dim tmp
Dim counter
Dim c As Range
Dim firstAddress
Dim rng As Range
ReDim findValues(1 To 3)
findValues(1) = "Curren" & "*" & "Core"
findValues(2) = "dummyvariable1"
findValues(3) = "dummyvariable2"
counter = 0
r = Range("A163").End(xlDown).Row
Set rng = Range(Cells(163, 1), Cells(r, 1))
Set This = ThisWorkbook
For Each tmp In rng
Workbooks.Open tmp
Set Wrbk = ActiveWorkbook
'For Each sht In Wrbk.Worksheets
Set sht = ActiveSheet
For i = 1 To 3
With sht.Range(Cells(1, 1), Range("A1").SpecialCells(xlCellTypeLastCell))
Set c = .Find(findValues(i), LookIn:=xlValues)
If Not c Is Nothing Then
firstAddress = c.Offset(0, 1).Value
secondAddress = c.Offset(0, 3).Value
thirdAddress = c.Offset(0, 4).Value
Do
This.Activate
tmp.Offset(0, 4).Value = firstAddress
Set c = .FindNext(c)
counter = counter + 1
Loop While Not c Is Nothing And c.Value = firstAddress
End If
End With
Wrbk.Activate
Next
'Wrbk.Activate
'Next sht
Wrbk.Close
Next tmp
End Sub
Have played around with the code a bit. The dummy variables will be in use for other functions, but basically the gist is to open a workbook, find a cell, take the cell next to it, paste in the original workbook. The problem is it picks up multiple cells that contain a string. I have used "Curren" & "Core" as the macro doesn't seem to handle spaces in strings to well.
Change
Set c = .Find(findValues(i), LookIn:=xlValues)
to
Set c = .Find(findValues(i), LookIn:=xlValues, LookAt:=xlWhole)
to require that the entire cell match the search string, rather than just part of the cell.
Related
I have a spreadsheet with values starting at A5 and running across to column AI, there could be any number of entries to the rows.
Row A contains an Item code (e.g. 000-0000)
I am looking to produce some code to complete the following two actions:
If column AI = yes, then copy entire row and paste below. With every copy add a sequential alphabetised letter to the code in column A (e.g. 000-0000a)
Any help would be greatly appreciated. Everything i've found expands to copying to another sheet and i'm struggling to break down the code.
Thanks
Edit:
Please see below current code I have been trying to get to work which works up to the point of copying the row however fails to paste it.
Sub NewItems(c As Range)
Dim objWorksheet As Worksheet
Dim rngNewItems As Range
Dim rngCell As Range
Dim strPasteToSheet As String
'Used for the new worksheet we are pasting into
Dim objNewSheet As Worksheet
Dim rngNextAvailbleRow As Range
'Define the worksheet with our data
Set objWorksheet = ThisWorkbook.Sheets("Sheet1")
'Dynamically define the range to the last cell.
'This doesn't include and error handling e.g. null cells
'If we are not starting in A1, then change as appropriate
Set rngNewItems = objWorksheet.Range("A5:A" & objWorksheet.Cells(Rows.Count, "A").End(xlUp).Row)
'Now loop through all the cells in the range
For Each rngCell In rngNewItems.Cells
objWorksheet.Select
If rngCell.Value <> "Yes" Then
'select the entire row
rngCell.EntireRow.Select
'copy the selection
Selection.Copy
'Now identify and select the new sheet to paste into
Set objNewSheet = ThisWorkbook.Sheets("Sheet1" & rngCell.Value)
objNewSheet.Select
'Looking at your initial question, I believe you are trying to find the next available row
Set rngNextAvailbleRow = objNewSheet.Range("A1:A" & objNewSheet.Cells(Rows.Count, "A").End(xlUp).Row)
Range("A" & rngNextAvailbleRow.Rows.Count + 1).Select
ActiveSheet.Paste
End If
Next rngCell
objWorksheet.Select
objWorksheet.Cells(1, 1).Select
'Can do some basic error handing here
'kill all objects
If IsObject(objWorksheet) Then Set objWorksheet = Nothing
If IsObject(rngBurnDown) Then Set rngNewItems = Nothing
If IsObject(rngCell) Then Set rngCell = Nothing
If IsObject(objNewSheet) Then Set objNewSheet = Nothing
If IsObject(rngNextAvailbleRow) Then Set rngNextAvailbleRow = Nothing
End Sub
So there are lots of things to address with your code. Many of which I have touched on. But the main thing to observe is that you are testing Column A not Column AI for the presence of "Yes" - so there may not be a match hence no copy.
As the paste destination is determined by a concatenation to create a sheet name you should have a test to ensure that sheet exists.
For testing I simply ensured a sheet called Sheet1a existed, that Sheet1 cell A5 had "a" in it, and there was a "Yes" in column AI. This could be improved but is enough to get you going.
This line is looping column A:
Set rngNewItems = objWorksheet.Range("A5:A" & lastRow)
Whereas this line is testing column AI:
If rngCell.Offset(, 35).Value <> "Yes"
Note <> means Not Equal as opposed to =
So perhaps you wanted:
If rngCell.Offset(, 35).Value = "Yes"
Consider the following re-write.
Option Explicit
Public Sub NewItems() 'c As Range) 'I have commented out parameter which isn't currently used.
Dim rngBurnDown As Range ' not used but also not declared
Dim objWorksheet As Worksheet
Dim rngNewItems As Range
Dim rngCell As Range
Dim strPasteToSheet As String
Dim objNewSheet As Worksheet
Dim lastRowTargetSheet As Long
Set objWorksheet = ThisWorkbook.Sheets("Sheet1")
Dim lastRow As Long
lastRow = objWorksheet.Cells(Rows.Count, "A").End(xlUp).Row
Set rngNewItems = objWorksheet.Range("A5:A" & lastRow)
Dim copiedRange As Range 'for union
For Each rngCell In rngNewItems.Cells
'Debug.Print rngCell.Address 'shows where looping
If rngCell.Offset(, 35).Value = "Yes" Then
Set objNewSheet = ThisWorkbook.Sheets("Sheet1" & rngCell.Value)
Dim nextTargetCell As Range
lastRowTargetSheet = objNewSheet.Cells(Rows.Count, "A").End(xlUp).Row
Set nextTargetCell = objNewSheet.Range("A" & lastRowTargetSheet)
rngCell.EntireRow.Copy nextTargetCell
Set objNewSheet = Nothing 'clear inside loop as you are setting in loop
lastRowTargetSheet = 0
Set nextTargetCell = Nothing
End If
Next rngCell
objWorksheet.Cells(1, 1).Select
End Sub
As for your lettering:
There are lots of examples online to generate these. Here is one way, by #harfang, from here:
Sub List_A_to_ZZZZ()
Dim i As Long
For i = 1 To 20 ' I have shortened this QHarr. Original end was 475254 ' ColXL("ZZZZ")
Debug.Print Right("---" & XLcL(i), 4)
Next i
End Sub
Function XLcL(ByVal N As Long) As String
Do While N > 0
XLcL = Chr(vbKeyA + (N - 1) Mod 26) & XLcL
N = (N - 1) \ 26
Loop
End Function
Function ColXL(ByVal abc As String) As Long
abc = Trim(Replace(UCase(abc), "-", ""))
Do While Len(abc)
ColXL = ColXL * 26 + (Asc(abc) - vbKeyA + 1)
abc = Mid(abc, 2)
Loop
End Function
I am looking to highlight certain cells in a spreadsheet when a value is entered in a different column. I realize this can be done with conditional formatting but, due to circumstances within the company, I must use VBA. (The spreadsheet is passed onto another program that can't read conditional formatting)
I am trying to highlight 11 different columns within my range of values whenever ANYTHING is entered into column L. For example, when a date it entered in L2, then C2, J2, K2, etc. are highlighted yellow.
Below is what I have come up with.. unfortunately, when I run the macro, nothing happens. I see it run, but I get no results - not even an error message. Thanks in advance for the time you take to help me out!
Dim rng As Range, r As Range
Set wb = ThisWorkbook
Set sht1 = wb.Sheets("From GIS")
Set sht2 = wb.Sheets("To MapCall")
Set rng = Intersect(sht2.UsedRange, Range("L:L")).Cells
For Each r In rng
If r.Value = "" Then
Cells(r.Row + 1, "C,J,K,Q,AI,AV,AW,AX,AY,AZ,BR").Interior.Color = RGB(255, 255, 0)
End If
Next r
Please give this a try and change r.Value = "" to r.Value <> "" as you want to apply a color if something is entered in the range not when it is blank. Tweak it as per what you actually need. I am also not sure why have you used r.Row + 1? It that's not what you want, replace i = r.Row + 1 in the below code with i = r.Row.
Also it's a good practice to declare all the variables used in the code.
Dim wb As Workbook
Dim sht1 As Worksheet, sht2 As Worksheet
Dim rng As Range, r As Range, clrRng As Range
Dim i As Long
Set wb = ThisWorkbook
Set sht1 = wb.Sheets("From GIS")
Set sht2 = wb.Sheets("To MapCall")
Set rng = Intersect(sht2.UsedRange, Range("L:L")).Cells
For Each r In rng
If r.Value = "" Then
i = r.Row + 1
Set clrRng = Union(Range("C" & i), Range("J" & i & ":K" & i), Range("Q" & i), Range("AI" & i), Range("AV" & i & ":AZ" & i), Range("BR" & i))
clrRng.Interior.Color = RGB(255, 255, 0)
End If
Next r
One method would be to create a union of ranges.
Sub test()
Dim Rng As Range, r As Range, uRng As Range, row As Long
Set wb = ThisWorkbook
Set sht1 = wb.Sheets("From GIS")
Set sht2 = wb.Sheets("To MapCall")
Set Rng = Intersect(sht2.UsedRange, Range("L:L")).Cells
For Each r In Rng
If r.Value <> "" Then
row = r.row
Set uRng = Union(Cells(row, "C"), Cells(row, "J")) 'Etc... Keep going with each column
uRng.Interior.Color = RGB(255, 255, 0)
End If
Next r
End Sub
I have written a macro to remove rows containing certain text in it. If either of the keyword contains any text, the macro will delete the row. However, the macro doesn't work at all. Perhaps, i did something wrong in it. Hope somebody will help me rectify this. Thanks in advance.
Here is what I'm trying with:
Sub customized_row_removal()
Dim i As Long
i = 2
Do Until Cells(i, 1).Value = ""
If Cells(i, 1).Value = "mth" Or "rtd" Or "npt" Then
Cells(i, 1).Select
Selection.EntireRow.Delete
End If
i = i + 1
Loop
End Sub
The keyword within the text I was searching in to delete:
AIRLINE DRIVE OWNER mth
A rtd REPAIRS INC
AANA MICHAEL B ET AL
ABASS OLADOKUN
ABBOTT npt P
AIRLINE AANA MTH
ABASS REPAIRS NPT
Try like this.
What about Using Lcase.
Sub customized_row_removal()
Dim rngDB As Range, rngU As Range, rng As Range
Dim Ws As Worksheet
Set Ws = Sheets(1)
With Ws
Set rngDB = .Range("a2", .Range("a" & Rows.Count))
End With
For Each rng In rngDB
If InStr(LCase(rng), "mth") Or InStr(LCase(rng), "rtd") Or InStr(LCase(rng), "npt") Then
If rngU Is Nothing Then
Set rngU = rng
Else
Set rngU = Union(rngU, rng)
End If
End If
Next rng
If rngU Is Nothing Then
Else
rngU.EntireRow.Delete
End If
End Sub
VBA syntax of your Or is wrong,
If Cells(i, 1).Value = "mth" Or "rtd" Or "npt" Then
Should be:
If Cells(i, 1).Value = "mth" Or Cells(i, 1).Value = "rtd" Or Cells(i, 1).Value = "npt" Then
However, you need to use a string function, like Instr or Like to see if a certain string is found within a longer string.
Code
Option Explicit
Sub customized_row_removal()
Dim WordsArr As Variant
Dim WordsEl As Variant
Dim i As Long, LastRow As Long
Dim Sht As Worksheet
WordsArr = Array("mth", "rtd", "npt")
Set Sht = Worksheets("Sheet1")
With Sht
' get last row in column "A"
LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
For i = LastRow To 2 Step -1
For Each WordsEl In WordsArr
If LCase(.Cells(i, 1).Value) Like "*" & WordsEl & "*" Then
.Rows(i).Delete
End If
Next WordsEl
Next i
End With
End Sub
I try to make my code sample as I can if you have any question please ask
Private Sub remove_word_raw()
'PURPOSE: Clear out all cells that contain a specific word/phrase
Dim Rng As Range
Dim cell As Range
Dim ContainWord As String
'What range do you want to search?
Set Rng = Range("A2:A25")
'sub for the word
shorttext1 = "mth"
shorttext2 = "rtd"
shorttext3 = "npt"
'What phrase do you want to test for?
ContainWord1 = shorttext1
ContainWord2 = shorttext2
ContainWord3 = shorttext3
'Loop through each cell in range and test cell contents
For Each cell In Rng.Cells
If cell.Value2 = ContainWord1 Then cell.EntireRow.Delete
Next
For Each cell In Rng.Cells
If cell.Value2 = ContainWord2 Then cell.EntireRow.Delete
Next
For Each cell In Rng.Cells
If cell.Value2 = ContainWord3 Then cell.EntireRow.Delete
Next cell
End Sub
Looking in the Column "U" unit ( 1 ) and the opposite of that cell in the Column "E" extracting hyperlink, then paste it on a new sheet (and so each unit)
I wrote a program , but it does not give needed result .
Sub подготовительная()
Dim r As Range
Dim rng As Range
Dim book1 As Workbook
Dim str As String
Dim gbr As Range
Set book1 = Workbooks.Open("E:\...\Вопрос.xlsx")
'переходим в активную книгу на 1-ую страницу и выделяем диапозон
book1.Worksheets("7").Activate
Set rng = book1.Worksheets("7").Range("U33:U99")
'находим первую 1
Set r = rng.Find(What:="1")
'запоминаем 1-ый адресс
firstAddress = r.Address
'другая переменная
Set gbr = r.Offset(, -16)
'забираем гиперссылку
str = gbr.Hyperlinks.Item(1).Address
'вставляем в Лист1
book1.Worksheets("Лист1").Cells(1, 1).Value = str
'ищем вторую 1
book1.Worksheets("7").Activate
Set r = r.FindNext(r)
If r.Address <> firstAddress Then
Set gbr = r.Offset(, -16)
str = gbr.Hyperlinks.Item(1).Address
book1.Worksheets("Лист2").Cells(1, 1).Value = str
Else: Exit Sub
End If
'ищем третью 1
book1.Worksheets("7").Activate
Set r = r.FindNext(r)
If r.Address <> firstAddress Then
Set gbr = r.Offset(, -16)
str = gbr.Hyperlinks.Item(1).Address
book1.Worksheets("Лист3").Cells(1, 1).Value = str
Else: Exit Sub
End If
End Sub
I think your mistakes is in:
Set r = r.FindNext(r)
where you're trying to find the next occurrence if "1" in range r instead of rng
so you should use
Set r = rng.FindNext(r)
Furthermore you may want to shorten your code down with the use of a loop, a string array (where to store your three sheets names: "Лист1", "Лист2" and "Лист3") and some With statements, like follows:
Option Explicit
Sub main()
Dim r As Range
Dim firstAddress As String
Dim iLoop As Long
Dim sheetNames(1 To 3) As String
sheetNames(1) = "Лист1" '<--| change it with your actual 1st sheet name
sheetNames(2) = "Лист2" '<--| change it with your actual 2nd sheet name
sheetNames(3) = "Лист3" '<--| change it with your actual 3rd sheet name
With Workbooks.Open(E:\...\Вопрос.xlsx").Worksheets("7").Range("U33:U99") '<--| open wanted workbook and refer to cells "U33:U99" in its worksheet "7"
Set r = .Find(What:="1") '<--| the Find() method is called on the range referred to in the preceding With statement
If Not r Is Nothing Then
firstAddress = r.Address
Do
iLoop = iLoop + 1 '<-- update loop counter
.Parent.Parent.Worksheets(sheetNames(iLoop)).Cells(1, 1).value = r.Offset(, -16).Hyperlinks.item(1).Address '<--| write into proper worksheet whose name is taken from sheetNames array at index corresponding to current loop
Set r = .FindNext(r) '<--| the FindNext() method is still called on the same range as in the preceding .Find() statement
Loop While Not r Is Nothing And r.Address <> firstAddress And iLoop < 3 '<--| exit loop if either you hit the first link or completed three loops
End If
End With
End Sub
I've got the following code that works very slowly. Any ideas on how to make faster?
Some background, in a previous Sub I had taken a range and then copy and pasted it. Now I need to change the values according to the code. Would it be possible to take this range and subject it to the modifications without pasting it first maybe?
Sub ChangeArea()
Dim Book As Workbook
Dim Sheet As Worksheet
Dim AreaRange As Range
Dim LastRow
Dim c As Range
Set Book = Workbooks("Testing")
Set Sheet = Book.Worksheets("Data")
Sheet.Activate
LastRow = Sheet.Cells(Rows.Count, "AG").End(xlUp).Row
Set AreaRange = Sheet.Range("AG5:AG" & LastRow)
For Each c In AreaRange.Cells
If c.Value = "10" Then
c.Value = "Mark"
ElseIf c.Value = "will" Then
c.Value = "William"
ElseIf c.Value = "Uncle" Then
c.Value = "Bill"
ElseIf c.Value = "Roomate" Then
c.Value = "Robert"
Else: End If
Next
End Sub
An option may be to use the Replace method on your range. See below and try to accommodate into your worksheet.
Sub ChangeThem()
Dim rng As Range
Dim lRow As Long
lRow = Sheet1.Cells(Rows.Count, "AG").End(xlUp).Row
Set rng = Sheet1.Range("AG5:AG" & lRow)
rng.Replace what:=1, replacement:="One"
rng.Replace what:=2, replacement:="Two"
rng.Replace what:=3, replacement:="Three"
End Sub
Try adding
Application.ScreenUpdating = false
to the top and
Application.ScreenUpdating = True
to the bottom
This keeps the screen from updating on every change.