# Index row in record if not blank

**URL:** <https://forum.openrefine.org/t/index-row-in-record-if-not-blank/1965>\
**Category:** Support and Helpdesk\
**Created:** [December 16, 2024, 9:45pm UTC](https://forum.openrefine.org/t/index-row-in-record-if-not-blank/1965 "2024-12-16T21:45:07Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![archilecteur](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.openrefine.org/archilecteur/32/1099_2.png) [@archilecteur](https://forum.openrefine.org/u/archilecteur)\
**Post date:** [December 16, 2024, 9:45pm UTC](https://forum.openrefine.org/t/index-row-in-record-if-not-blank/1965/1 "2024-12-16T21:45:07Z")

</div>

Dear Pro Refiners,

When creating a new column, how do I index, within a record, only those lines containing a value?  
Surprisingly, I've been struggling with this problem for hours.

 ![indexIfNotBlank](https://europe1.discourse-cdn.com/flex017/uploads/openrefine/original/2X/8/8ba6dc3939f327fac4a2314044c5284868b01366.jpeg)

---

<div class="post-metadata">

**Author:** ![Antoine2711](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.openrefine.org/antoine2711/32/85_2.png) [@Antoine2711](https://forum.openrefine.org/u/Antoine2711)\
**Post date:** [December 17, 2024, 4:26am UTC](https://forum.openrefine.org/t/index-row-in-record-if-not-blank/1965/2 "2024-12-17T04:26:12Z")

</div>

Salut Julien,

I would do it in 5 steps.

1. Create a backup column of the index
2. Permanently reorder the column with missing values so that the empty elements are at the end.
3. Hide them with a facet
4. Do you command to create the new column with your data
5. Using the saved index, reorder permenently the rows to the original order.

Bonne chance, Antoine

---

<div class="post-metadata">

**Author:** ![thadguidry](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.openrefine.org/thadguidry/32/653_2.png) [@thadguidry](https://forum.openrefine.org/u/thadguidry)\
**Post date:** [December 17, 2024, 11:00am UTC](https://forum.openrefine.org/t/index-row-in-record-if-not-blank/1965/3 "2024-12-17T11:00:49Z")

</div>

Curious, why do you feel you have to "index" within a record when it is always provided? There's always an index of rows from/to in a record and the number of rows, and the array of cells in a given column of a record.

Perhaps we/you could add a paragraph that might help others with what you feel is missing and important in our Records documentation:

> **[Expressions | OpenRefine](https://openrefine.org/docs/manual/expressions#record)**
>
> Overview

---

<div class="post-metadata">

**Author:** ![thadguidry](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.openrefine.org/thadguidry/32/653_2.png) [@thadguidry](https://forum.openrefine.org/u/thadguidry)\
**Post date:** [December 17, 2024, 11:33am UTC](https://forum.openrefine.org/t/index-row-in-record-if-not-blank/1965/4 "2024-12-17T11:33:13Z")

</div>

But maybe you want to show the `row.record.index` ONLY if the columns value is not blank?  
`forNonBlank(value,v,row.record.index,null)`

 ![image](https://europe1.discourse-cdn.com/flex017/uploads/openrefine/original/2X/6/635569e8a39819a5564578afa18ac9c10d5bdf51.png)

Otherwise, if you are trying to RE-index, then like @Antoine2711 is hinting at, you will need to push this out to a new column.

---

<div class="post-metadata">

**Author:** ![archilecteur](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.openrefine.org/archilecteur/32/1099_2.png) [@archilecteur](https://forum.openrefine.org/u/archilecteur)\
**Post date:** [December 17, 2024, 1:45pm UTC](https://forum.openrefine.org/t/index-row-in-record-if-not-blank/1965/5 "2024-12-17T13:45:25Z")

</div>

@thadguidry, thanks for the replies. Indeed, I want to apply the indexing only to the column values that are not blank. However, my aim here is to achieve (sub)level indexing, i.e. instead of 1,1,1,1,1... 2,2,2,2,2... to obtain 1,2,3,4,5,6... 1,2,3,4,5,6... on non-blank values only.

---

<div class="post-metadata">

**Author:** ![archilecteur](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.openrefine.org/archilecteur/32/1099_2.png) [@archilecteur](https://forum.openrefine.org/u/archilecteur)\
**Post date:** [December 17, 2024, 1:55pm UTC](https://forum.openrefine.org/t/index-row-in-record-if-not-blank/1965/6 "2024-12-17T13:55:19Z")

</div>

Salut @Antoine2711, thanks for the reply. I’ll try that route. I have many similar tables to which I have to add this column, which is why I was looking for a more straightforward solution.

---

<div class="post-metadata">

**Author:** ![ostephens](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.openrefine.org/ostephens/32/8_2.png) [@ostephens](https://forum.openrefine.org/u/ostephens)\
**Post date:** [December 17, 2024, 2:41pm UTC](https://forum.openrefine.org/t/index-row-in-record-if-not-blank/1965/7 "2024-12-17T14:41:23Z")

</div>

@archilecteur are your values in column unique (i.e. within a single record, would have repetitions of the same value in the `web-scraper-order` column)?

If they are you can "Add column based on this column" with the transformation:

```auto
forEach(forEachIndex(row.record.cells["web-scraper-order"].value,i,v,v.toString()+"|"+(i+1).toString()),w,if(w.split("|")[0]==value,w.split("|")[1],null)).join("|")

```

To break this down a bit:  
`row.record.cells["web-scraper-order"].value` gives you an array of all the non-null values for this column within the current record.  
So  
`forEachIndex(row.record.cells["web-scraper-order"].value,i,v,v.toString()+"|"+(i+1).toString())`  
builds an array that concatenates (as a string) the value from the cell with the place (index) of that value in the list of non-null values in the record (we add one to the index to count from 1 instead of zero)

So if we start with something like:

| Column 1 | Column 2 |
| --- | --- |
| 1 | a |
| | _null_ |
| | b |
| | c |
| 2 | d |
| | |

then `forEachIndex(row.record.cells["Column 2"].value,i,v,v.toString()+"|"+(i+1).toString())` gives an output of `["a|1","b|1","c|3"]` for rows 1-4 (record 1), and `["d|1"]` for row 5 (record 2)

The outer `forEach` then iterates through this array created by the `forEachIndex` and if the value in the current cell matches the first part of a value in the array (i.e. we are in the right row), it stores the index (split out from the string), otherwise it stores a _null_

Finally `join` is used to get a single string output from the array, ignoring any null values. So we get something like:

| Column 1 | Column 2 | Output of forEachIndex | Output of forEach | Output of join (final output) |
| --- | --- | --- | --- | --- |
| 1 | a | ["a|1","b|2","c|3"] | [1,null,null] | 1 |
| | null | ["a|1","b|2","c|3"] | [null,null,null] | null |
| | b | ["a|1","b|2","c|3"] | [null,2,null] | 2 |
| | c | ["a|1","b|2","c|3"] | [null,null,3] | 3 |
| 2 | d | ["d|1"] | [1] | 1 |

You can, of course, add a final `.toNumber()` on the end of the expression to get a sortable integer if that's what you need.

This approach fails if you have repeated values in the column as your `forEach` will result in an array with more than one non-null entry. I'm not sure what the solution would be in that case, although my instinct is that there's probably a way around it given some more thought.

---

<div class="post-metadata">

**Author:** ![archilecteur](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.openrefine.org/archilecteur/32/1099_2.png) [@archilecteur](https://forum.openrefine.org/u/archilecteur)\
**Post date:** [December 17, 2024, 3:58pm UTC](https://forum.openrefine.org/t/index-row-in-record-if-not-blank/1965/8 "2024-12-17T15:58:06Z")

</div>

@Antoine2711, it works as expected. Thanks again for the help.

---

<div class="post-metadata">

**Author:** ![archilecteur](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.openrefine.org/archilecteur/32/1099_2.png) [@archilecteur](https://forum.openrefine.org/u/archilecteur)\
**Post date:** [December 17, 2024, 4:03pm UTC](https://forum.openrefine.org/t/index-row-in-record-if-not-blank/1965/9 "2024-12-17T16:03:31Z")

</div>

@ostephens, all of the identifiers from web-scraper should be unique. However, there may be one or many blank values per record, which is a repetition technically.

---

<div class="post-metadata">

**Author:** ![ostephens](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.openrefine.org/ostephens/32/8_2.png) [@ostephens](https://forum.openrefine.org/u/ostephens)\
**Post date:** [December 17, 2024, 4:17pm UTC](https://forum.openrefine.org/t/index-row-in-record-if-not-blank/1965/10 "2024-12-17T16:17:22Z")

</div>

@archilecteur - sorry I should have been clear I meant any repeated non-null values.

> all of the identifiers from web-scraper should be unique

In that case adding a column using

```auto
forEach(forEachIndex(row.record.cells["web-scraper-order"].value,i,v,v.toString()+"|"+(i+1).toString()),w,if(w.split("|")[0]==value,w.split("|")[1],null)).join("|")

```

should work for you

---

<div class="post-metadata">

**Author:** ![archilecteur](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.openrefine.org/archilecteur/32/1099_2.png) [@archilecteur](https://forum.openrefine.org/u/archilecteur)\
**Post date:** [December 17, 2024, 4:57pm UTC](https://forum.openrefine.org/t/index-row-in-record-if-not-blank/1965/11 "2024-12-17T16:57:27Z")

</div>

Damn. You did it again @ostephens.  
Thank you.
