Dyota's blog

#hashtags

#hashtags, or getting unique values across multiple table rows

An app that I made for work allows for users to post ideas into a digital suggestion box. One of the features of the entry form is that users can write in their own "special tags" that act as hashtags. An entry could carry multiple tags.

In the app, I have a table view, for which I have a series of filters. One of the filters is for the special tags. I need to select a tag of choice, and all of the entries for that tag need to show.

I had hacked this together in the beginning using some Find() functions and it really didn't work very well. In the end, I revisited it a few times and managed to pull off some table manipulations that looks like it could go blow for blow with Power Query.

Let have a look at it!

The full code

Too long; didn't read. Here it is.

Distinct(
    Sort(
        Filter(
            Split(
                Concat(
                    Filter(
                        
                        table,
                        
                        !IsBlank(Tags)
                    ).Tags,
                    Tags,
                    ";"
                ),
                ";"
            ).Result,
            Len(Result)>0
        ).Result,
        Trim(Result),
        Ascending
    ), Result
)

To analyse this, we need to work inside out. But first, let me show you what this is processing.

Scenario

Let's use a simple example. See this simplified table:

Title Tags
Entry 1 Engineering; Materials; AI
Entry 2 Tendering; Engineering;
Entry 3 Tendering; Business Development; AI
Entry 4

I have a filter that's a dropdown list of unique tag values.

Tags
AI
Business Development
Engineering
Materials
Tendering

When I select Engineering, I need to see these results (let's not worry about this filtering function for now):

Title Tags
Entry 1 Engineering; Materials; AI
Entry 2 Tendering; Engineering;

And when I select AI, I need to see this:

Title Tags
Entry 1 Engineering; Materials; AI
Entry 3 Tendering; Business Development; AI

Data Storage

I get users to put in their custom tags as a semicolon-separated series of strings, and that's how I store it. It gets sent to a SharePoint column of type "single-line text" and it stays there verbatim.

The main trick is getting the unique values of tags in the first place. Let's start taking a look at the code.

Bring it together

It doesn't help that all of the data values are spread out across multiple rows. If we need to get a single list, we need to bring them in together first.

The first thing I do is filter for the rows that have tags on them. I access the Tags column because that's the only one I'm interested in.

Filter(
    table,
    !IsBlank(Tags)
).Tags

Using our imagination, we should have this as an intermediate result.

Tags
Engineering; Materials; AI
Tendering; Engineering;
Tendering; Business Development; AI

The next thing I do is concatenate them all, using a semicolon as separator. (I'll abbreviate previously evaluated expressions as a "...".)

Concat(
    ...,
    Tags,
    ";"
)

Intermediate result:

Engineering; Materials; AI ; Tendering; Engineering; Tendering; Business Development; AI

This already looks like the final result is within reach. If we just turn this into a table, we can filter for distinct values and voila!

Creating a tags table

That's exactly what the Split() function is for.

Split(
    ...,
    ";"
).Result
Result
Engineering
Materials
AI
Tendering
Engineering
Tendering
Business Development
AI

Notice that the table that results is one with a single column, called Results.

Cleanup

The next two functions are for cleanup. In the real data, we may get two consecutive semicolons, which results in an empty row. We don't want those.

Filter(
    ...,
    Len(Result)>0
).Result,

It would be nice if the values were alphabetical. We also don't want any errant spaces before or after our values. Notice how I stack these functions together, but having Trim() in the sort expression argument of Sort().

Sort(
        ...,
    Trim(Result),
    Ascending
)

Let's check in with our intermediate result. It will have been sorted alphabetically, A-Z.

Result
AI
AI
Business Development
Engineering
Engineering
Materials
Tendering
Tendering

The final distinct

Finally, use Distinct() on all of this to get our desired result.

Distinct(
    ..., 
    Result
)

We end up with our target result.

Tags
AI
Business Development
Engineering
Materials
Tendering

That's it!

#powerapps