Actually I want to check spacing and format of my Values Using VBA Macro. It is a dynamic string say 1 Count (Pack of 1) or 2 Count (Pack of 1), 20 g (Pack of 1) or 50 g (Pack of 2), 100 ml (Pack of 2) or 200 ml (Pack of 1). so the format remains the same but the integer alone changes in each cell. Also I wrote a code using instr function but it is not able to validate and give me the output. I want integer to be be defined as X and format should be the same.
I have mentioned the code below which I tried. I need some concept which can be helpful. I have attached the screenshot which needs to be validated. Thanks a lot.
Sub QualityCheck()
Dim LastColumn As Long
Dim X(1 To 20000) As Integer
ActiveSheet.Select
Range("A1").Select
LastColumn = ActiveSheet.Cells(1, Columns.Count).End(xlToLeft).Offset(0, 1).Columns.Select
ActiveCell.Value = "Quality Error"
Range("A1").Select
Set P = Range("A$1:AD$1")
For Each cell In P
If cell.Value = "ASIN" Then cell.Offset(1, 0).Select
Next
Do While ActiveCell.Value <> ""
If ActiveCell.Offset(0, -2).Value = "DE" Then
If ActiveCell.Offset(0, 12).Value Like " Stück ( er Pack)" Then
ActiveCell.Offset(0, 26).Value = " Correct"
End If
End If
ActiveCell.Offset(1, 0).Select
Loop
End Sub
Also I have tried like declaring a varaible like X = 1 to 1000 and concat "X&" Stuck ("&X&"er Pack")" but still it didne work. It would be helpful if I get the syntax to crack the concept. Thanks in advance.
From what I understood you need to modify this line:
If ActiveCell.Offset(0, 12).Value Like "*Stück (*er Pack)" Then
This modification goes like this:
Any char - then followed by "Stück (" then ANY CHARS - followed by "er Pack)"
Should work, let me know if it did!
Hope it helps.
Related
Beyond ordinary Latin characters, Excel somehow does a pretty good job of sorting strings in various alphabets.
< and > in formulae use that same order.
But < and > in VBA use a different order - probably given by Unicode().
The extract below shows the inconsistency between columns B and C.
How can I compare strings in VBA using the same order that is used for sorting?
I am hoping that while X < Y will not give the relevant result, somefunction(X) < somefunction(Y) will do so.
I have found some articles/postings about how to change the sort order, but that is not the issue here.
Apologies for the above being an image - I can't work out how to get Excel data in to SO.
For replication:
The values in column A are: А Б В Г Ґ Д Е Є Ж З И Stop, starting from A2, which is named "first"
The formula in B2 is =IF(A2<A3,"Less than next","Greater than next")
The formula in D2 is =UNICODE(A2)
Column C is populated by the macro:
Sub Compare()
Range("first").Select
Do Until ActiveCell.Value = "Stop"
If ActiveCell.Value < ActiveCell.Offset(1, 0).Value Then
ActiveCell.Offset(0, 2).Value = "Less than next"
ElseIf ActiveCell.Value > ActiveCell.Offset(1, 0).Value Then
ActiveCell.Offset(0, 2).Value = "Greater than next"
Else
ActiveCell.Offset(0, 2).Value = "Same as next"
End If
ActiveCell.Offset(1).Select
Loop
End Sub
You can force VBA to use a different comparison method when comparing strings.
This can be done for a whole module, putting Option Compare Text at the top of the code - if done, you can use the regular comparison operators like < to > without changing your code (Default setting is Option Compare Binary)
You can also do this indiviually for a single comparison using the function strComp and pass vbTextCompare as third parameter (omitting tge third parameter will let VBA fall back to the defined Option Compare)
StrComp(cell.Value, cell.Offset(1, 0).Value, vbTextCompare)
Note that the text sorting option also will see upper and lower case characters as "equal".
Not 100% sure if those will always get the same results as the Excel compare, but at least for your given examples it did. If you don't trust this, you can fall back to the Evaluate-method that really uses the Excel-engine.
Option Compare Text
Sub Compare()
Dim cell As Range
Set cell = ThisWorkbook.Sheets(1).Range("A2")
Do Until cell.Value = "Stop"
Dim formula As String, res As Variant
formula = """" & cell.Value & """ < """ & cell.Offset(1, 0).Value & """"
res = Application.Evaluate(formula)
cell.Offset(0, 1) = getCmpInfostr(res)
cell.Offset(0, 2) = getCmpInfostr(cell.Value < cell.Offset(1, 0).Value)
cell.Offset(0, 3) = getCmpInfostr(StrComp(cell.Value, cell.Offset(1, 0).Value))
cell.Offset(0, 4) = getCmpInfostr(StrComp(cell.Value, cell.Offset(1, 0).Value, vbTextCompare))
Set cell = cell.Offset(1, 0)
Loop
End Sub
Function getCmpInfoString(c As Variant)
If VarType(c) = vbBoolean Then
c = IIf(c, -1, 1)
End If
If VarType(c) <> vbInteger And VarType(c) <> vbLong Then
getCmpInfostr = "invalid"
ElseIf c < 0 Then
getCmpInfostr = "Less than"
ElseIf c > 0 Then
getCmpInfostr = "Greater than"
Else
getCmpInfostr = "Same"
End If
End Function
Obligatory hint for all VBA programming: avoid Select and ActiveCell - see How to avoid using Select in Excel VBA
The following code shows the different methods - let the code run once with and once without the Option Compare Text option.
I need to delete rows that have cells containing ®.
Cells(iCntr, 6).Value = "*®*"
Cells(iCntr, 6).Value = "®"
I have also tried setting condition_ranges and conditions instead - I have not been able to get anything to work in regard to the special character.
Sub Remove()
Dim lRow As Long
Dim iCntr As Long
lRow = 1000
For iCntr = lRow To 1 Step -1
If Cells(iCntr, 6).Value = "BLK" Then
Rows(iCntr).Delete
ElseIf Cells(iCntr, 6).Value = "WHI" Then
Rows(iCntr).Delete
ElseIf Cells(iCntr, 7).Value = "*®*" Then
Rows(iCntr).Delete
End If
Next
End Sub
The code works just fine for the "BLK" and "WHI" but nothing is taken out using the "®". There are no error messages it just does not modify the worksheet.
You can use Like:
ElseIf Cells(iCntr, 7).Value Like "*®*" Then
The question could be translated to "How to check whether a string contains a specific substring", because once this part is resolved, then the corresponding cell could be deleted.
InStr is a function, that compares two strings, returning the position of the second one within the first one. If the second one is not found in the first one, then 0 is returned. With some fantasy, this could be used to see whether the (R) is present:
Sub TestMe()
Debug.Print ThePresenceOfR("kt®b")
Debug.Print ThePresenceOfR("tzv")
End Sub
Function ThePresenceOfR(str As String) As Boolean
ThePresenceOfR = InStr(1, str, "®")
End Function
Or as mentioned in the other answer, kt®b Like "*®*" would deliver the same results.
I have a macro that inserts 2 columns on my current sheet and pastes information from another sheet.
I want to create 2 variables that are assigned to each column that would change the next time I run the macro to paste the information in the next two columns.
Columns("BO:BO").Select
Selection.Insert Shift:=xlToRight
Range("BO2").Select
ActiveCell.FormulaR1C1 = "Feb weekly-wk 2"
Range("BO19").Select
ActiveCell.FormulaR1C1 = _
"=VLOOKUP(Comparison!RC2,'Jan16 wk4'!R3C15:R34C24,9,FALSE)"
Range("BO19").Select
Selection.AutoFill Destination:=Range("BO19:BO47"), Type:=xlFillDefault
Range("BO19:BO47").Select
Columns("BP:BP").Select
Selection.Insert Shift:=xlToRight
Range("BP2").Select
Selection.Style = "20% - Accent6"
Range("BP2").Select
ActiveCell.FormulaR1C1 = "Diff"
Range("BP19").Select
ActiveCell.FormulaR1C1 = "=RC[-2]-RC[-1]"
My idea is to set up a variable that I would replace my current "BO" and "BP" code with.
Dim X as String, Y as String
X = "BO"
y = "BP"
When I run the macro it would change the variable for this example "BO" to "BQ" and "BP" to "BR". Next time I run the macro would change the "BQ" to "BS" and "BR" to "BT".
I just cleaned your code a little:
Dim ColBO As Integer
Dim ColBP As Integer
Dim StrBO As String
Dim StrBP As String
StrBO = "BO"
StrBP = "BP"
ColBO = ActiveWorkbook.Range(StrBO & 1).Column 'instead of StrBO you could directly write ("BO" & 1)
ColBP = ActiveWorkbook.Range(StrBP & 1).Column 'Then you wouldnt need these two variables
Columns(ColBO).Insert Shift:=xlToRight
'Columns(ColBO).Select ' Trying to avoid selection but not sure if this works here...
'Selection.Insert Shift:=xlToRight
Range(1, ColBO).FormulaR1C1 = "Feb weekly-wk 2"
Range(19, ColBO).FormulaR1C1 = "=VLOOKUP(Comparison!RC2,'Jan16 wk4'!R3C15:R34C24,9,FALSE)"
Range(19, ColBO).AutoFill Destination:=Range("BO19:BO47"), Type:=xlFillDefault
Columns(ColBP).Insert Shift:=xlToRight 'Same here as above
Range(2, ColBP).Style = "20% - Accent6"
Range(2, ColBP).FormulaR1C1 = "Diff"
Range(19, ColBP).FormulaR1C1 = "=RC[-2]-RC[-1]"
For the future: If you can, try to avoid .Select/Selection/.Activate if possible. The code can mostly run without such commands and without activating a cell. ;)
If you are not actually writing BO/BP to the range you are transforming I would go with two ints, stored in a hidden sheet. Read/write each time you run the macro.
This is, in my opinion, the easier solution, other places to go would be global variables or storing it to a file.
If you want to use numeric variables you can change approach and use Cells instead of Range:
'You can use the rows below to know the column number
Range("BO1").Activate
ActiveCell.Value = ActiveCell.Column 'This way you get the column number into the cell
ColNum = ActiveCell.Column 'This way you get the column number into the variable
'So now you know that BO column number is 67 and you can use
Cells(1, 67) = "OK"
'Or, using variables:
RowNum = 1
ColNum = 67
Cells(RowNum, ColNum) = "You Got It!"
This makes you able to loop columns simply using a for ... next
If you need to loop from BO to BR you can use
For ColNum = 67 To 70
Cells(1, ColNum) = "OK"
Next ColNum
Hope it helps.
Do Until Selection.Value = "" Or _
(Selection.Value = theyear And Selection.Offset(0, 1).Value = themonth)
Selection.Offset(1, 0).Select
Loop
in this line of statement, the code is unable to check the condition with the or part ie; it does not check the condition in the bracket. Is it expected?
Try this:
Sub Test()
Dim sMonth As String
Dim iYear As Integer
sMonth = UCase(Trim(InputBox("Enter the first three alphabets of the month to append", "Month Initials")))
iYear = InputBox("Enter the year to which the month corresponds", "Year")
Do Until Selection.Value = "" Or _
(UCase(Trim(Selection.Value)) = sMonth And Selection.Offset(0, 1).Value = iYear)
Selection.Offset(1, 0).Select
Loop
End Sub
Your main mistake was to put a variable name between quotes.
However, I want to make note that this code may be quite sensible to bugs due to the fact that you allow the user to input any data without check.
But if it's for own use, this doesn't really matter.
Also note that .Select/Offset makes your code overall pretty rigid.
I want to check:
IF cells (i,"A") contains the text 'Miami' AND (i,"D") contains the text 'Florida' THEN change value of cell (i,"C") to BA.
Sub ABC()
Dim wsh As Worksheet, i As Long, lngEndRowInv As Long
Set wsh = ActiveSheet
i = 2
lngEndRowInv = wsh.Range("A" & wsh.Rows.Count).End(xlUp).Row
While i <= lngEndRowInv
If Cells(i, "A") like "*Miami*" And Cells(i, "D") like "*Florida*" Then
Cells(i, "C").Value = "BA"
End If
i = i + 1
Wend
End Sub
Brief syntax lesson
Cells(Row, Column) identifies a cell. Row must be an integer between 1 and the maximum for version of Excel you are using. Column must be a identifier (for example: "A", "IV", "XFD") or a number (for example: 1, 256, 16384)
.Cells(Row, Column) identifies a cell within a sheet identified in a earlier With statement:
With ActiveSheet
:
.Cells(Row,Column)
:
End With
If you omit the dot, Cells(Row,Column) is within the active worksheet. So wsh = ActiveWorkbook wsh.Range is not strictly necessary. However, I always use a With statement so I do not wonder which sheet I meant when I return to my code in six months time. So, I would write:
With ActiveSheet
:
.Range.
:
End With
Actually, I would not write the above unless I really did want the code to work on the active sheet. What if the user has the wrong sheet active when they started the macro. I would write:
With Sheets("xxxx")
:
.Range.
:
End With
because my code only works on sheet xxxx.
Cells(Row,Column) identifies a cell. Cells(Row,Column).xxxx identifies a property of the cell. Value is a property. Value is the default property so you can usually omit it and the compiler will know what you mean. But in certain situations the compiler can be confused so the advice to include the .Value is good.
Cells(Row,Column) like "*Miami*" will give True if the cell is "Miami", "South Miami", "Miami, North" or anything similar.
Cells(Row,Column).Value = "Miami" will give True if the cell is exactly equal to "Miami". "MIAMI" for example will give False. If you want to accept MIAMI, use the lower case function:
Lcase(Cells(Row,Column).Value) = "miami"
My suggestions
Your sample code keeps changing as you try different suggestions which I find confusing. You were using Cells(Row,Column) <> "Miami" when I started typing this.
Use
If Cells(i, "A").Value like "*Miami*" And Cells(i, "D").Value like "*Florida*" Then
Cells(i, "C").Value = "BA"
if you want to accept, for example, "South Miami" and "Miami, North".
Use
If Cells(i, "A").Value = "Miami" And Cells(i, "D").Value like "Florida" Then
Cells(i, "C").Value = "BA"
if you want to accept, exactly, "Miami" and "Florida".
Use
If Lcase(Cells(i, "A").Value) = "miami" And _
Lcase(Cells(i, "D").Value) = "florida" Then
Cells(i, "C").Value = "BA"
if you don't care about case.
If there are no typos in the question, you got the conditions wrong:
You said this:
IF cells (i,"A") contains the text 'Miami'
...but your code says:
If Cells(i, "A") <> "Miami"
--> <> means that the value of the cell is not equal to "Miami", so you're not checking what you think you are checking.
I guess you want this instead:
If Cells(i, "A") like "*Miami*"
EDIT:
Sorry, but I can't really help you more. As I already said in a comment, I'm no Excel VBA expert.
Normally I would open Excel now and try your code myself, but I don't even have Excel on any of my machines at home (I use OpenOffice).
Just one general thing: can you identify the row that does not work?
Maybe this helps someone else to answer the question.
Does it ever execute (or at least try to execute) the Cells(i, "C").Value = "BA" line?
Or is the If Cells(i, "A") like "*Miami*" stuff already False?
If yes, try checking just one cell and see if that works.
If you are simply looking for the occurrence of "Miami" or "Florida" inside a string (since you put * at both ends), it's probably better to use the InStr function instead of Like. Not only are the results more predictable, but I believe you'll get better performance.
Also, VBA is not short-circuited so when you use the AND keyword, it will test both sides of the AND, regardless if the first test failed or not. In VBA, it is more optimal to use 2 if-statements in these cases, that way you aren't checking for "Florida" if you don't find "Miami".
The other advice I have is that a for-each loop is faster than a for-loop. Using .offset, you can achieve the same thing, but with better effeciency. Of course there are even better ways (like variant arrays), but those will add a layer of complexity not needed in this example.
Here is some sample code:
Sub test()
Application.ScreenUpdating = False
Dim lastRow As Long
Dim cell As Range
lastRow = Range("A" & Rows.Count).End(xlUp).Row
For Each cell In Range("A1:A" & lastRow)
If InStr(1, cell.Value, "Miami") <> 0 Then
If InStr(1, cell.Offset(, 3).Value, "Florida") <> 0 Then
cell.Offset(, 2).Value = "BA"
End If
End If
Next
Application.ScreenUpdating = True
End Sub
I hope you find some of this helpful, and keep at it with VBA! ^^
I think you should append .value in IF statement:
If Cells(i, "A").Value <> "Miami" And Cells(i, "D").Value <> "Florida" Then
Cells(i, "C").Value = "BA"
End IF