cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
DanielSkogvik
Frequent Visitor

Compare strings and highlight differences

Hi

I have created an app where the user can submit a request to change the content of a text.

This request is subject to approval by the manager.

The manager wants to more easily see exactly what has changed from previous text.

I want to highlight all the changes.

(This is test screen - in the app i compare data from database, not textinput field)

 

 

ForAll(
    Split(lblOriginalTekst.Text;"");
    Collect(samTelleverk1; 1);;
    Collect(samOriginal; {Linje: CountRows(samTelleverk1); original: ThisRecord.Result})
);;

ForAll(
    Split(lblEndretTekst.Text;"");
    Collect(samTelleverk2; 1);;
    Collect(samEndret; {Linje: CountRows(samTelleverk2); endret: ThisRecord.Result})
);;

If(
    CountRows(samOriginal) < CountRows(samEndret);
    ClearCollect(
        samNyBase;
        AddColumns(
            samEndret;
            "original";
            LookUp(samOriginal; Linje = samEndret[@Linje]; original);
            "match";
            false
        )
    );
    ClearCollect(
        samNyBase;
        AddColumns(
            samOriginal;
            "endret";
            LookUp(samEndret; Linje = samOriginal[@Linje]; endret);
            "match";
            false
        )
    )
);;

ForAll(
    Sequence(CountRows(samNyBase));
    UpdateIf(samNyBase; endret = original; {match: true})
)

 

 

 

 

 

Concat(samNyBase; If(match = false; endret; Substitute(endret;endret; " ")); "")

 

 

DanielSkogvik_0-1613245817339.png

 

This compares character to character, and if you add a letter early in the text, all characters will consequently appear as incorrect.

Can anyone help me solve this in a better way? Thanks in advance 🙂

7 REPLIES 7
Eelman
Super User
Super User

@DanielSkogvik 

I don't think you can do any better than what you've already achieved. 

 

You could try try using a 3rd Party text comparison software to do what you want but currently there's nothing available in PowerApps to do this. 

 

Another option would be to be to display the original and new text side-by-side then use your code to highlight the differences but you'd likely need 3 text controls ie Orig || Diff || New to do this.

 

Sorry I couldn't be more help here but this is pretty cool code though, nice work!

RandyHayes
Super User III
Super User III

@DanielSkogvik 

Had to chime in on this one...a couple of things.  

1) You are wasting the output of your ForAll functions.  ForAll is not a For/Loop as much as it is a function the returns a table.  So, you can highly optimize your Formula by cutting out the heavy-weight collections for intermediate steps and just put the ForAll results directly into the Collection.

2) I am not sure exactly what your word/line comparison is based on.  Ex. in your scenario, The Quick Brown Fox Jumped  compared to A Quick Brown Fox Jumped would show everything after A to be changed as you are comparing character to character.

 

If you are looking for more of a word to word comparison. Something like this:

 
 

Screenshot 2021-02-13 204238.png

It is quite easy to achieve without any collections of other button pressing to get to it.

In the above I have a TextInput1 and TextInput2 and an HtmlText control.

The Formula for the HtmlText of the HtmlText control is the following:

With({_originalInput: TextInput1.Text, _compareInput: TextInput2.Text},
    With({
        _original:
            With({_ori:Filter(MatchAll(_originalInput, "\S*(\s|\n?)"), !IsBlank(FullMatch))},
                ForAll(Sequence(CountRows(_ori)),
                   {Word: Last(FirstN(_ori, Value)).FullMatch, Pos: Value}
                )
            ),
        _changes:
            With({_ori:Filter(MatchAll(_compareInput, "\S*(\s|\n?)"), !IsBlank(FullMatch))},
                ForAll(Sequence(CountRows(_ori)),
                    {Word: Last(FirstN(_ori, Value)).FullMatch, Pos: Value}
                )
            )
        },
        Concat(_original As _ori, 
            With({_change: LookUp(_changes, Pos=_ori.Pos)},
                If(_ori.Word <> _change.Word, "<s>" & _ori.Word & "</s>&nbsp;<font color=red>" & _change.Word & "</font>", _ori.Word) & "&nbsp;"
            )
        )
    )
)
 

This will produce the output as mentioned - without any collections or other steps.

In your case, you can just substitute into the first two "parameters" (_originalInput and _compareInput) the values you are retrieving from your datasource.

 

You'll notice the use of the ForAll in the above for it's original purpose...to return a table.

 

I hope this is helpful for you, and would be happy to answer any questions.

 

 
 
 
 
 

 

 

   

_____________________________________________________________________________________
Digging it? - Click on the Thumbs Up. Solved your problem? - Click on Accept as Solution. Others seeking the same answers will be happy you did.
Check out my PowerApps Videos too!

My mind is blown away 🙂

I have dived into your formula and i understand what you did. Fantastic! Simple, efficient and clean. And yes, so true - i'm wasting the output of both ForAll-loops. Never thought of it that way.

In the past hour i have learned the With function and what MatchAll actually returns. This is my first time trying out the Power Apps community that i have read so much about. And it really came true and helped me 🙂 Thank you so much.

There is one more question i have. If you look at this scenario:

screenshot_1.JPG

 

 

 

 

 

 

 

 

Works great!

 

But when i add a new word, like this:

screenshot_2.JPG



 

 

 

 

 

Every word is marked as changed. And that is of course because it is checking word against word based on position. And when the position changes, it is no longer comparing against the correct word.

 

Is there any way of solving this by changing something in the regex expression, or do you have to solve this in the comparing logic?

 

I'm thinking something in the line of counting the words in both original and changed, and if the word count is different - change what word you are comparing to?

RandyHayes
Super User III
Super User III

@DanielSkogvik 

Yes, the one thing you will get from my responses - simple and efficient (or at least I strive for that).  Too many things are overcomplicated when they need not be.  

So, I am glad this worked for you.

 

As for the scenario - yes, this was one of the things that was a factor because this is a Word-By-Word comparison.

This particular solution does not account for inserted words.  That becomes a bit challenging but doable.  

I didn't offer that process as, when I looked at your original, you seemed to deem the rest of the string to be invalid at the first occurrence of an inserted character to the end of the string.  So wasn't sure that was needed. 

Is that something you need in this scenario or, is the original good?

_____________________________________________________________________________________
Digging it? - Click on the Thumbs Up. Solved your problem? - Click on Accept as Solution. Others seeking the same answers will be happy you did.
Check out my PowerApps Videos too!

Yes, that is something we need in this scenario. Every change in text from user is accepted (change words, adding/removing etc.). It just needs to be highlighted so that the managers can see what changes are made. The same way changes in words are highlighted in the current version you kindly provided 🙂

RandyHayes
Super User III
Super User III

@DanielSkogvik 

I'm working on this for you.  I did this in another app a while back and can't seem to recall which one.  I realized it would be faster for me to recreate it rather than search through hundreds of apps to find it.

So...give me a little bit 🙂

_____________________________________________________________________________________
Digging it? - Click on the Thumbs Up. Solved your problem? - Click on Accept as Solution. Others seeking the same answers will be happy you did.
Check out my PowerApps Videos too!

I have been looking at javascript/other languages to see how they have solved it, and i can see that this is VERY complicated. 1000++ lines of code. So many scenarios. So i will definitely understand if this is something we have to find a different solution for..

Helpful resources

Announcements
PA User Group

Welcome to the User Group Public Preview

Check out new user group experience and if you are a leader please create your group

MBAS Attendee Badge

Claim Your Badge & Digital Swag!

Check out how to claim yours today!

secondImage

Are Your Ready?

Test your skills now with the Cloud Skill Challenge.

secondImage

Demo Extravaganza is Back!

We are excited to announce that Demo Extravaganza for 2021 has started!

MBAS on Demand

Microsoft Business Applications Summit sessions

On-demand access to all the great content presented by the product teams and community members! #MSBizAppsSummit #CommunityRocks

Top Solution Authors
Top Kudoed Authors
Users online (34,589)