Find first value in a range greater than a reference cell value

I have a range of cells containing values in no order. I want to scan back up (or down) the list and find the first cell value greater than the reference cell.
IE a1:a10 contains 3,7,12,2,5,8,24,32,6,3 and a11 contains 15. I want to find the first cell in the range a1:a10 has a value greater than the value in a11. So if searching ascending I want a8 and if descending a7.

Do you use ā€œascendingā€ for upwards (starting at the bottom element of the column) and ā€œdescendingā€ for downwards?

Yes, in that instance.

Please see below - I have attached the complete macro that does what I (think!) I wantā€¦

Hallo

=INDEX(FILTER(A1:A10;A1:A10>A11);1)    #for the first value >A11
=LET(x;FILTER(A1:A10;A1:A10>A11);INDEX(x;COUNT(x)))  # for the last value >A11

both Formulas for LO24.8 or later!!

1 Like

Thanks for that. But Iā€™m on 24.2.7.2 - apologies - I should have stated that in my initial post.

=INDEX(A1:A10;MINIFS(ROW(A1:A10);A1:A10;">"&A11))  #first ā€¦
=INDEX(A1:A10;MAXIFS(ROW(A1:A10);A1:A10;">"&A11)) #last ā€¦
3 Likes

Thanks for the input, but I get a ā€˜VALUE!ā€™ error from that. My actual code is:
=INDEX(B93:B267,MINIFS(ROW(B93:B267),B93:B267,">"&B268))

ā€¦MINIFS(ROW(B1:B175),B93:B267,">"&B268))

In this latter form, it would become difficult to keep the number of rows in sync. Despite looking more complex, this form could be a bit simpler in maintenance:

MINIFS(ROW(B93:B267)-ROW(B93)+1;B93:B267;">"&B268))

Iā€™m doing something wrong, as Iā€™m getting either Value errors or zero. Thanks though both for your help. Iā€™ll play around a bit now youā€™ve given me some pointers.

I have written a macro to do what I want (took me a while). The code seems to work APART from the formatting of the output cells.
The macro runs over a column and checks if the value in that column has a bigger or smaller value in the past - and if so posts when tjose events happened and what the values were. I want the macro to revisit the whole colum each time it is run in case I have manually changed any values. So the macro needs to blank values where it may have posted values in the past. It does that OK - BUT - the blank values are being shown as Ā£0.00 and an 1899 date. Is there a way to reset a cell to nothing? My code for the posting bit is:

' We have the current row and which row then has a bigger value and a smaller value.....so now post into d/e bigger date and value and f/g smaller date and value
SUB postValues(p_currSheet,p_currRow, p_dateCol,p_valCol, p_foundbigger,p_foundsmaller)

 DIM l_biggerCol1		AS INTEGER
 DIM l_smallerCol1		AS INTEGER
 DIM l_biggerCell		AS OBJECT
 DIM l_biggerVal1		AS STRING
 DIM l_biggerVal2		AS STRING
 DIM l_smallerCell		AS OBJECT
 DIM l_smallerVal1		AS STRING
 DIM l_smallerVal2		AS STRING
 DIM l_destCell			AS OBJECT
 
 	' l_bigger.......
 	' Date column.....
 	IF p_foundBigger THEN
 		l_biggerCell		= p_currSheet.getCellByPosition(p_dateCol,p_foundBigger)
 		l_biggerVal1		= l_biggerCell.VALUE
 		' Value Column
 		l_biggerCell		= p_currSheet.getCellByPosition(p_valCol,p_foundBigger)
 		l_biggerVal2		= l_biggerCell.VALUE	
 	ELSE
 		l_biggerVal1		= ""
 		L_biggerVal2		= ""	
 	END IF	
 
 	l_destCell				= p_currSheet.getCellByPosition(p_dateCol+3,p_currRow)
 	l_destCell.setValue(l_biggerVal1)
 	l_destCell				= p_currSheet.getCellByPosition(p_valCol+3,p_currRow)
 	l_destCell.setValue(l_biggerVal2)

 	
 	' l_smaller.......as bigger
 	IF p_foundSmaller THEN
 		l_smallerCell		= p_currSheet.getCellByPosition(p_dateCol,p_foundSmaller)
	 	l_smallerVal1		= l_smallerCell.VALUE
	 	l_smallerCell		= p_currSheet.getCellByPosition(p_valCol,p_foundSmaller)
 		l_smallerVal2		= l_smallerCell.VALUE
 	ELSE
 		l_smallerVal1		= ""
 		L_smallerVal2		= ""
 	END IF
 
 	l_destCell				= p_currSheet.getCellByPosition(p_dateCol+5,p_currRow)
 	l_destCell.setValue(l_smallerVal1)
 	l_destCell				= p_currSheet.getCellByPosition(p_valCol+5,p_currRow)
 	l_destCell.setValue(l_smallerVal2)

	MSGBOX "Posted Bigger Val1 (" & l_biggerVal1 & "} Val2 (" & l_biggerVal2 & ") Smaller Val1 (" & l_smallerVal1 & ") Val2 (" & l_smallerVal2 & ") Into (" & p_dateCol+3 & ") (" & p_valCol+3 & ") (" & p_dateCol+5 & ") (" & p_valCol+5 & ")"
	
END SUB 'postValues

ā€¦the ā€œā€ gets posted, but I want really a l_destCell.unSetValue(). Is there such a thing ?

[erAck: edited to format code as code, see This is the guide - How to use the Ask site? - #6 by erAck]

If user code is acceptable, you may also be interested in
disask114371match.ods (41.7 KB)

This is the full macro. It assumes two columns are populated - A and B - column A had dates in ascending order and column B has a set of random values. The macro then looks back up column A to find the last populated row - then looks at column B , and using the last value in that column populates columns D/E and F/G. Column D is the last time (ie the date from col A ) the Value in B was bigger than the last value in B, and Col E is then the value that exceeded the last value - columns F and G are similar but for smaller values (ie when was the last date that the value was smaller than the last entry in Col B)
The code follows.


'  *****  BASIC  *****
 TYPE t_found
	bigger				AS INTEGER
	smaller				AS INTEGER
 END TYPE
 
' What I want to do here is to take a value from the current cell and go back over a rang of cells and find the last time
' the range had a value bigger (or smaller) than the current cell
' This is for pension growth ioe the current value is Ā£10 and it was Ā£13 two days back (or it was Ā£7 five days ago)

SUB Main
 
 DIM l_sheetName        AS STRING
 DIM l_StartRow			AS INTEGER
 DIM l_EndRow			AS INTEGER
 DIM l_currSheet 		AS OBJECT
 DIM l_dateCol			AS INTEGER
 DIM l_valCol			AS INTEGER
 DIM l_currRow			AS INTEGER
 
 DIM m_found			AS NEW t_found

    ' NB the top lef is 0,0 NOT 1,1 so col A is 0, B is 1 etc - ditto rows - Row 1 is 0, 2 is 1.. Why?
    '    whay don't they adjust that in the functions?
    l_sheetName		= "Pension Growth"
    l_dateCol		= 0
    l_valCol		= 1
	l_EndRow      	= 93
	l_StartRow		= 5000
	'l_currSheet		= ThisComponent.getCurrentController.activeSheet
	l_currSheet		= ThisComponent.getCurrentController.activeSheet

	
	IF (l_currSheet.name <> l_sheetName) THEN
		MSGBOX "Wrong Sheet (" & l_currSheet.name & ") - Only Works On (" & l_sheetName & ")"
	ELSE
		MSGBOX l_currSheet.name
		' StartRow is initially set to 5000 ( roughly 10 years of data) and gets modified by getMaxRow
		' checkCol is A (0) - see which cols have dates and values (col B = 1)
		l_StartRow    	= getMaxRow(l_currSheet,l_dateCol,l_StartRow,l_EndRow)
	
		FOR l_currRow = l_StartRow TO l_EndRow STEP - 1
	    
			m_found     = findRows(l_currSheet,l_currRow,l_valCol,l_StartRow,l_EndRow)
		
			' Now use m_found to populate cols d (3) as bigger date, e (4) as bigger value, f(5) as smaller date and g (6) as smaller value
			postValues(l_currSheet,l_currRow,l_dateCol,l_valCol,m_found.bigger,m_found.smaller)
		
		NEXT l_currRow
	END IF	
	
END SUB 'Main			
	
' Get the max row.. this is the start point - start looking 5000 rows down and come back up the sheet until a non blank date (col 0 - ie A)
' Returns the max row where a date and value is present
SUB getMaxRow(p_currSheet,p_dateCol,p_StartRow,p_EndRow) AS INTEGER
 DIM l_row          	AS INTEGER
 DIM l_cell				AS OBJECT

 	MSGBOX "StartRow (" & p_StartRow & ") LowRow (" & p_EndRow & ") Col (" & p_dateCol & ")"
 	
 	FOR l_row = p_StartRow TO p_EndRow STEP -1
		IF p_currSheet.getCellByPosition(p_dateCol,l_row).TYPE <> 0 THEN
			IF p_currSheet.getCellByPosition(p_dateCol +1,l_row).TYPE <> 0 THEN
				EXIT FOR
			END IF
		END IF		
	NEXT l_row			
	
	MSGBOX "Got Start Row Of (" & l_row & ") Cell Value (" & p_currSheet.getCellByPosition(p_dateCol,l_row).VALUE & ")"
	getMaxRow	=	l_row
	
END SUB ' getMaxRow	   
    
   
' Find the next row (going up) that has a bigger or smaller value than the current row
SUB findRows(p_currSheet,p_currRow,p_valCol,p_StartRow,p_EndRow) AS t_found
 DIM l_currRow			AS INTEGER
 DIM l_currCell			AS OBJECT
 DIM l_currCellValue	AS STRING
 DIM l_astr				AS STRING
 DIM l_myStr			AS STRING

 DIM l_found			AS NEW t_found
 
	l_found.bigger		= 0
	l_found.smaller		= 0
	 
   	l_checkValue		= p_currSheet.getCellByPosition(p_valCol,p_currRow).value
    
	FOR l_currRow 		= p_currRow TO p_EndRow STEP -1
		
		l_currCellValue	= p_currSheet.getCellByPosition(p_valCol,l_currRow).value
		
		IF l_found.bigger THEN
		ELSE
			IF l_currCellValue > l_checkValue THEN
				l_found.bigger	= l_currRow
			END IF
		END IF	
		
		IF l_found.smaller THEN
		ELSE
			IF l_currCellValue < l_checkValue THEN
				l_found.smaller	= l_currRow
		 	END IF
		END IF 	
		
		IF l_found.bigger AND l_found.smaller THEN
			EXIT FOR
		END IF	
	
	NEXT l_currRow
	
'	l_myStr = l_myStr & " Check Value ( " & l_checkValue & ") Found Bigger In (" & l_found.bigger & ") Smaller In (" & l_found.smaller & ")"
		 
'	MSGBOX l_myStr
	
	findRows	= l_found
 	
END SUB ' -- findRows

' We have the current row and which row then has a bigger value and a smaller value.....so now post into d/e bigger date and value and f/g smaller date and value
SUB postValues(p_currSheet,p_currRow, p_dateCol,p_valCol, p_foundbigger,p_foundsmaller)

 DIM l_biggerCol1		AS INTEGER
 DIM l_smallerCol1		AS INTEGER
 DIM l_biggerCell		AS OBJECT
 DIM l_biggerVal1		AS STRING
 DIM l_biggerVal2		AS STRING
 DIM l_smallerCell		AS OBJECT
 DIM l_smallerVal1		AS STRING
 DIM l_smallerVal2		AS STRING
 DIM l_destCell			AS OBJECT
 
 	' l_bigger.......
 	IF p_foundBigger THEN
 		' Date column.....
 		l_biggerCell		= p_currSheet.getCellByPosition(p_dateCol,p_foundBigger)
 		l_biggerVal1		= l_biggerCell.VALUE
 		' Value Column
 		l_biggerCell		= p_currSheet.getCellByPosition(p_valCol,p_foundBigger)
 		l_biggerVal2		= l_biggerCell.VALUE	
 	ELSE
 		l_biggerVal1		= ""
 		L_biggerVal2		= ""	
 	END IF	
 
 	l_destCell				= p_currSheet.getCellByPosition(p_dateCol+3,p_currRow)
 	l_destCell.setValue(l_biggerVal1)
 	l_destCell				= p_currSheet.getCellByPosition(p_valCol+3,p_currRow)
 	l_destCell.setValue(l_biggerVal2)

 	
 	' l_smaller.......as bigger
 	IF p_foundSmaller THEN
 		l_smallerCell		= p_currSheet.getCellByPosition(p_dateCol,p_foundSmaller)
	 	l_smallerVal1		= l_smallerCell.VALUE
	 	l_smallerCell		= p_currSheet.getCellByPosition(p_valCol,p_foundSmaller)
 		l_smallerVal2		= l_smallerCell.VALUE
 	ELSE
 		l_smallerVal1		= ""
 		L_smallerVal2		= ""
 	END IF
 
 	l_destCell				= p_currSheet.getCellByPosition(p_dateCol+5,p_currRow)
 	l_destCell.setValue(l_smallerVal1)
 	l_destCell				= p_currSheet.getCellByPosition(p_valCol+5,p_currRow)
 	l_destCell.setValue(l_smallerVal2)

'	MSGBOX "Posted Bigger Val1 (" & l_biggerVal1 & "} Val2 (" & l_biggerVal2 & ") Smaller Val1 (" & l_smallerVal1 & ") Val2 (" & l_smallerVal2 & ") Into (" & p_dateCol+3 & ") (" & p_valCol+3 & ") (" & p_dateCol+5 & ") (" & p_valCol+5 & ")"
	
END SUB 'postValues

ā€¦the only problem (I think) I have is when the values change and I need to blank a value. I get an 1899 date and 0 in the D/E,F/G columns and I really want them to be blank. Itā€™s probably an error in the code that I havenā€™t spotted.

[erAck: edited to format code as code, see This is the guide - How to use the Ask site? - #6 by erAck]

ask114371.ods (14.3 KB)

OK - fixed that final issue. The code uses setValue even when Iā€™m trying to ā€˜blankā€™ the cell. That then gives me the 1899 date and 0.00 value - so I thought Iā€™d record a macro of what hitting delete does in a cell - and that showed me a call to a uno method of clearContents. So I googled a bit more and that clearContents method is then available in my case - so I used this type of code:
ā€¦IF l_smallerVal1 = "" THEN l_destCell.clearContents(7) ELSE l_destCell.setValue(l_smallerVal1) END IFā€¦

ā€¦and that works fine. So if there are no bigger or smaller values I now get blanks in the cells rather than 1899 and 0.00.
If anyone wants the full macro, let me know and Iā€™ll post the whole thing.