I'm out of idea how I could format consecutive same (respectively only even) values in Excel tables without using VBA.
The conditional formatting shall color only consecutive values and only
all 0s or all even values, when there are not more than 2.
A: ID
B: binary
C: counting
1
1
1
2
0
2
3
0
2
4
1
3
5
0
4
6
0
4
7
0
4
8
1
5
9
1
5
I tried to format with: =COUNTIF(C1:C9, C1) < 3, but then it also colors the 1s and C6:C7, eventho there are more than 2.
I also tried =AND( COUNTIF(C1:C9,C1) < 3, ISEVEN(C1:C9) ) but then it colors nothing.
I could replace the 0s with empty cells so I could check ISEMPTY(B1:B9) but it again colors nothing. Using $ to set absolute changes nothing as well.
Formating duplicates also colors triplets, which also doesn't work for me.
=OR(COUNTIF($C$1:$C$9,C1) = 1, COUNTIF($C$1:$C$6,C1) = 2) works so far, but also colors the 1s (uneven).
=AND(OR(COUNTIF($C$1:$C$9,C1) = 1, COUNTIF($C$1:$C$6,C1) = 2), ISEVEN($C$1:$C$9)) doesn't work.
=AND(OR(COUNTIF($C$1:$C$9,C1) = 1, COUNTIF($C$1:$C$6,C1) = 2), $B$1:$B$9 <> 1) doesn't work as well.
My only solution so far is using 2 formating rules:
color =OR(COUNTIF($C$1:$C$9,C1) = 1, COUNTIF($C$1:$C$6,C1) = 2)
do not color =$B$1:$B$9 = 1
but I think it is terrible.
I worked on it for some hours, maybe I'm missing something really obvious.
I'm not allowed to use VBA, therefore this is ot an option.
EDIT: My 2.rule-solution can be simplificed with:
color =COUNTIF($C$1:$C$9,C1) < 3
do not color =$B$1:$B$9 = 1
I'm still confused why combining both doesn't work:
AND(COUNTIF($C$1:$C$9,C1) < 3; $B$1:$B$9 <> 1)
EDIT2: I know why it didn't work. Don't check <>1 with absolute value-range $B$1$:$B$9
Solution: B1 <> 1 then it loops through.
Now combining both works:
=AND( COUNTIF($C$1:$C$9, C1) < 3, B1 <> 1)
I can't see an easy answer for the binary numbers. You have two cases:
(1) Current cell is zero, previous cell is 1, next cell is zero and next cell but one is 1.
(2) Current cell is zero, previous cell is zero, previous cell but one is 1, next cell is 1.
But then the first pair of numbers is a special case because there is no previous cell.
Strictly speaking the last pair of numbers is a special case as well because there is no following cell.
=OR(AND(ROW()=1,B$1=0,B$2=0,B$3=1),AND(ROW()=2,B$1=0,B$2=0,B$3=1),AND(B1=0,B1048576=1,B2=0,B3=1),AND(B1=0,B1048576=0,B1048575=1,B2=1))
where I have used the fact that you are allowed to wrap ranges to the end of the sheet (B1048576) in conditional formatting.
Adding the condition for the case where there there are two zeroes at the end of the range:
=OR(AND(ROW()=1,B$1=0,B$2=0,B$3=1),
AND(ROW()=2,B$1=0,B$2=0,B$3=1),
AND(B1=0,B1048576=1,B2=0,OR(B3=1,B3="")),
AND(B1=0,B1048576=0,B1048575=1,OR(B2=1,B2="")))
Even this could go wrong if there was something in the very last couple of rows of the sheet, so I suppose to be absolutely safe:
=OR(AND(ROW()=1,B$1=0,B$2=0,B$3=1),
AND(ROW()=2,B$1=0,B$2=0,B$3=1),
AND(Row()>1,B1=0,B1048576=1,B2=0,OR(B3=1,B3="")),
AND(Row()>2,B1=0,B1048576=0,B1048575=1,OR(B2=1,B2="")))
Shorter:
=OR(AND(ROW()<=2,B$1+B$2=0,B$3=1),
AND(B1+B2=0,B1048576=1,OR(B3=1,B3="")),
AND(B1+B1048576=0,B1048575=1,OR(B2=1,B2="")))
Not the cleanest wat but it works. You only need to move your data 1 row below, so headers would be in row 2 and data in row 3 for this formula to work:
=IF(AND(B3=B4,B3<>B5),IF(AND(B4=B3,B4<>B2),TRUE,FALSE),IF(AND(B3=B2,B3<>B1),IF(AND(B3=B4,B3<>B5),FALSE,TRUE),FALSE))
How about this approach (Office 365):
=LET(range,B$1:B$9,
s,IFERROR(TRANSPOSE(INDEX(range,ROW()+SEQUENCE(5,,-2))),1),
t,TEXTJOIN("",,(s=INDEX(range,ROW()))*ISEVEN(s)),
IFERROR(SEARCH("0110",t)<4,IFERROR(SEARCH("010",t)=2,FALSE)))
It creates an array s of 5 values starting point is the current row of the range, adding the 2 values above and below. If the value is out of range it will replace the error with a 1.
The array s is checked for being even (TRUE/FALSE, IFERROR created values are uneven) and the values to equal the value of the current row of the range (TRUE/FALSE).
These two booleans are multiplied creating 1 for both values being TRUE, else 0.
These values are joined and checked for 2 consecutive 1's (surrounded by 0) to be found in the 2nd or 3rd position of the range (this would be the case if two even consecutive equal numbers are found),
if it errors it will look if a unique even number is found (1 surrounded by 0 in 2nd position).
PS I'm unable to test if conditional formatting allows you to type the range as B:B instead of B$1:B$9 (working from a mobile) but that would make it more dynamical, because that way you can easily expand the conditional range.
I am a total noob. I need to grab the same cell value from every other sheet (starting at the third) in a workbook and place them into another. I continue to get an IndexError: list index out of range. There are 20 sheets in the workbook. I have imported xlrd and xlwt.
Code:
sheet_id = 3
output = 0
cellval = enso.sheet_by_index(sheet_id).cell(20,2).value
sheet_cp = book_cp.get_sheet(output)
sheet_cp.write(1, 1, cellval)
book_cp.save(path)
for sheet_id in range(0,20):
sheet_enso = enso_cp.get_sheet(sheet)
sheet_cp = book_cp.get_sheet(output)
sheet_cp.write(1, 1, cellval)
sheet_id = sheet_id + 2
output = output + 1
Your problem most probably exists in here:
sheet_id = 3
cellval = enso.sheet_by_index(sheet_id).cell(20,2).value # row:20, column:0
Check the following:
1- Make sure that sheet_id=3 is what you want (where the index of sheets starts from 0), so the 3rd sheet has index=2 unless you want the 4th sheet.
2- Check cell(20,0) exists in the selected sheet (where cell(0,0) is the first cell).
Plus, you don't need to define sheet_id
instead change the range to (2: 3rd sheet, 21: for 20 sheets) > in range(2,21) where:
range([start], stop[, step])
start: Starting number of the sequence.
stop: Generate numbers up to, but not including this number.
step: Difference between each number in the sequence.
Reference: Python's range() Parameters
and to get cellval from every sheet, put cellval inside the loop.
The final code could be:
output = 0
for sheet_id in range(2,21): # (starting at the 3rd sheet (index=2), stopping at 20 "21 not included")
cellval = enso.sheet_by_index(sheet_id).cell(20,0).value # row 20, column 0
#sheet_enso = enso_cp.get_sheet(sheet) # i don't know if you need that for something else
sheet_cp = book_cp.get_sheet(output)
sheet_cp.write(1, 1, cellval)
output = output + 1
book_cp.save(path)
again check cell(20,0) exists in all source sheets to avoid errors.
I am trying to compare decimal values in Excel VBA and delete rows that
match the criteria. This was my original code and it skipped over many rows.
For Each i In WSData.Range("A7", WSData.Range("A7").End(xlDown)).Cells
If i.Offset(0, 3).Value >= 98 Then
i.EntireRow.Delete
End If
Next
And the values on the spreadsheet are decimal values just with the % sign.
I tried "> 97.99" because Excel has some issues with floating point comparison but it still doesn't accurately compare.
Here is what it shows after using Selection.Value.
Percentages are decimal depicted with integers. For example 100.00% is stored as 1 and 98.01% is stored as .9801.
Therefor you need to adjust the threshold:
For Each i In WSData.Range("A7", WSData.Range("A7").End(xlDown)).Cells
If i.Offset(0, 3).Value >= .98 Then
i.EntireRow.Delete
End If
Next
The second problem is that when deleting rows it is best to iterate backwards. Otherwise it might miss some rows, because as each row is deleted it is moved up and then the next iteration skips the next row.
Change i from a range to a long and use this:
For i = WSData.Range("A7").End(xlDown).row to 7 Step -1
If WSData.Cells(i,3).Value >= .98 Then
Row(i).Delete
End If
Next
Edit: Because it appears there is a custom mask on the number format that is forcing numbers to look like percentages try this:
For i = WSData.Range("A7").End(xlDown).row to 7 Step -1
If WSData.Cells(i,3).Value >= 98 Then
Row(i).Delete
End If
Next
If this works then your main problem was that you were looking at column D. The offset is additive. So when you used .offset(0,3) it was moving three columns from column A. 1 + 3 is 4.
As the title says, I need to find the first column with an empty cell in every third row in my sheet.
It looks like this:
-----------
---------
-------
------
I need to write data from another sheet into each (third) row. That part of the code is ok, I checked it. But, for some reason, this code doesn't work:
For t = 5 To 500 Step 3
u = 0
For s = 5 To 500
If IsEmpty(Cells(t, s)) And s > g And u = 0 Then
g = s
u = 1
Exit For
End If
Next s
Next t
Its not clear what your problem is, but this will find the first blank cell in every third row and change it to a value you assign it.
Sub firstBlankEveryThirdRow()
For t = 5 To ActiveSheet.UsedRange.Rows.Count Step 3
Range("1:1").Offset(t - 1).Cells.SpecialCells(xlCellTypeBlanks)(1).Value = "Insert Your Value Here"
Next t
End Sub
Here's my problem:
I have two ranges, r_products and r_ptypes which are from two different sheets, but of same length i.e.
Set r_products = Worksheets("Products").Range("A2:A999")
Set r_ptypes = Worksheets("SKUs").Range("B2:B999")
I'm searching for something in r_products and I've to select the value at the same position in r_ptypes. The result of Find method is being stored in cellfound. Now, consider the following data:
Sheet: Products
A B C D
1 Product
2 S1
3 P1
4 P2
5 S2
6 S3
Sheet: SKUs
A B C D
1 SKU
2 S1-RP003
3 P1-BQ900
4 P2-HE300
5 S2-NB280
6 S3-JN934
Now, when I search for S1, cellfound.Row gives me value 2, which is, as I understand, 2nd row in the total worksheet, but is actually 1st row in the range(A2:A999).
When I use this cellfound.Row value to refer to r_ptypes.cells(cellfound.Row), It is taking it as an Index value and returns B3 (P1-BQ900) instead of what I want, i.e. B2 (S1-RP003).
My question is how'll I find out the index number in cellfound? If not possible, how can I use Row number to extract data from r_ptypes?
Dante's solution above works fine. Also, I managed to get the index value using built in excel function Match instead of using Find method of a range. Listing it here for reference.
indexval = Application.WorksheetFunction.Match("searchvalue", r_products, 0)
Using the above, I'm now able to refer the rows in r_ptypes
skuvalue = r_ptypes.Rows(indexval).Value
Because .Row always returns the absolute row number of a sheet, not the offset (i.e. index) in the range.
So, just do some minus job to deal with it.
For you example,
r_ptypes.Cells(cellfound.Row - r_ptypes.Cells(1).Row + 1)
or a little bit neat (?)
With r_ptypes
.Cells(cellfound.Row - .Cells(1).Row + 1)
End With
That is, get the row difference between cellfound and the first cell and + 1 because Excel counts cells from 1.