An arrayformula to find the previous non-empty cell in another column

In Google Spreadsheets, without using Apps Script etc., is it possible to achieve the following with a single formula, such as arrayformula (or maybe mmult or something strange, but no fill-down) at the top of Column B?:

scenario:

Column A: cells are empty or non-empty

goal:

Column B: contains the last non-empty cell of column A

example:

input | output
===============
a | a
------+--------
| a
------+--------
| a
------+--------
5 | 5
------+--------
| 5
------+--------
c | c
------+--------
c | c
------+--------
| c
------+--------
a | a
------+--------

=ArrayFormula(vlookup(ROW(1:10),{IF(LEN(A1:A10)>0,ROW(1:10),""),A1:A10},2))

Explanation

Assuming the input data in the Column A of the below table and that the above formula is in cell B1.

Note: In order to make easier to evaluate the formula, the Column A (input) doesn't repeat values but it will work with any kind of values (letters, numbers, symbols, repeated, unsorted, etc.)

|    A       B
=== + ======= =======
1  |    a       a
2  |            a
3  |    b       b
4  |            b
5  |            b
6  |    c       c
7  |    d       d
8  |    e       e
9  |            e
10  |    f       f

VLOOKUP was selected as it could be used to find approximate values and it could return multiple values (array).

As the input values could appear in any order, instead of using the actual values, the row number was used for non empty cells and empty cells have assigned an empty string "".

It was used LEN instead of ISBLANK because cells with formulas that return an empty string return FALSE and this could cause problems in some common scenarios.

IF(LEN(A1:A10)>0,ROW(1:10),"")

NOTE: In you want to save three characters, the second parameter ("" the character is the parameter separator ,) could be removed. When analysing this part of formula empty cells will return FALSE.

As VLOOKUP requires that the lookup up column be the first column, instead of a range, a "semi-manually" made array was used.

{IF(LEN(A1:A10)>0,ROW(1:10),""),A1:A10}

The above approach save us cells and processing time.

• Can be made a bit shorter by omitting "" in the if command (omitted argument is blank by default).
– user79865
Jan 7 '16 at 16:17
• Ah that's clever, I see you create a temporary lookup table mapping rows to values ({IF(...), ...} consists of rows 1->a, 3->b, 6->c, ... with some blank rows), then perform a lookup. Thank you also for the explanation! However what do you mean "In order to make easier to evaluate it, the column A (input) doesn't repeat values"? This seems to handle duplicate values (a b c a e ...), doesn't it? Jan 8 '16 at 8:34
• @ninjagecko: I was talking about the sample input data. I mentioned this because the OP included repeated data. I will reword that part to make that clearer.
– Rubén
Jan 8 '16 at 10:57
• @Normal: I didn't omit "" but added a note about that and replaced ROW(A1:A10) by ROW(1:10). :)
– Rubén
Jan 8 '16 at 11:38
• @ninjagecko: Maybe the use in my answer of the term "evaluate" is causing confusion due to your background. In your Web Apps profile you don't share much about it, but I can see that you have 35k reputation in SO, so I think that you use "evaluate" frequently as something done by a machine. In my case I my first thought about it something done by humans. In this case "whom" is the formula builder/adopter, specially those who have not used before vlookup and arrays together in Google Sheets.
– Rubén
Jan 10 '16 at 14:57

In addition to the previous post, below formula will allow the use of open-ended ranges so that output will 'auto-expand' when new values are added to the referenced column (A in the example below).

=ArrayFormula(
if(row(A2:A) <= max(if(not(isblank(A2:A)),row(A2:A))),
vlookup(row(A2:A),filter({row(A2:A),A2:A},len(A2:A)),2),
)
)

EDIT: if you don't want the output limited to the last row of the sourcedata, you can 'hardcode' the end row like this:

=ArrayFormula( if(row(A:A) <= 20, vlookup(row(A:A),filter({row(A:A),A:A},len(A:A)),2), ) )
• One caveat of this formula is that it "stops" on the last row of the data source. I think that this should be mentioned in the answer.
– Rubén
Mar 2 '16 at 22:47
• @Rubén: I think that can be easily amended. Let's say you want the output to continue after the last row of the source data (e.g.: row 20) you can change the formula to =ArrayFormula( if(row(A:A) <= 20, vlookup(row(A:A),filter({row(A:A),A:A},len(A:A)),2), ) )
– JPV
Mar 3 '16 at 7:45
• That should be mentioned in the answer too, I think.
– Rubén
Mar 3 '16 at 12:22
• @Rubén: I just did. ;-)
– JPV
Mar 3 '16 at 15:21

You can try this formula:

=ArrayFormula(if(ISBLANK(A1:A10);INDEX(A1:A10;ROW()-1;COLUMN());A1:A10))