Qlik Community

QlikView App Dev

Discussion Board for collaboration related to QlikView App Development.

Announcements
QlikWorld online is next week! REGISTER NOW
cancel
Showing results for 
Search instead for 
Did you mean: 
davidbalmer
Contributor III
Contributor III

Calculation of an Account Balance?

LOAD * INLINE [

    Acct, Balance, SalesPerson

    1212, 100, David

    1212, 100, Mike

    1212, 100, Lucy

    1525, 325, Jack

    1525, 325, Bill

    1525, 325, Edgar

    1630, 100, Paul

];

// In the preceding, I want only the Balance in the FIRST line of each Acct

// to be used in calculating a ClosingBal for each Acct.  I.E., for Acct 1212, the Balance is 100

//The calculation I need is the (Acct Balance) - count(SalesPerson) = ClosingBal where ClosingBal

//is the starting Balance for the next row in the Acct.

//The Report would look like the following:

Acct  Balance  SalesPerson ClosingBal

1212   100     David        99

1212    99     Mike         98

1212    98     Lucy         97

1525   325     Jack        324

1525   324     Bill        323

1525   323     Edgar       322

1630   100     Paul         99

// I only have QlikView Personal so I cannot process a 3rd party .qvw solution.  Anybody kind

// enough to help me would have to print out the solution.  I have spent two days on this with

// all kinds of approaches but still not got it.   Thanks  David

13 Replies
campbellr
Creator
Creator

Hi David

If you're wanting to achieve this in the load script, the following works:

tmp:

LOAD * INLINE [

    Acct, Balance, SalesPerson

    1212, 100, David

    1212, 100, Mike

    1212, 100, Lucy

    1525, 325, Jack

    1525, 325, Bill

    1525, 325, Edgar

    1630, 100, Paul

];

NoConcatenate

SPCount:

Load

if(Acct=Previous(Acct),BalancePrev - AcctCountRT - 1, Balance -1) as BalanceClose

    ,if (Acct=Previous(Acct), Balance - AcctCountRT ,Balance) as Balance

    ,Acct

    ,SalesPerson

    ;

Load   

    if (Acct=Previous(Acct), 1 + previous(AcctCount),0) as AcctCountRT

    ,*

    ;

Load

    Acct

    ,SalesPerson

    ,if(isnull(Previous(Balance)),Balance,Previous(Balance)) as BalancePrev

    ,Balance

    ,if (Acct=Previous(Acct),1,0) as AcctCount

Resident tmp;  

Drop table tmp;

davidbalmer
Contributor III
Contributor III
Author

Hi Ron:

It works perfectly.  I am now trying to digest how and why it works. I am a rookie at QV and have lots to learn.  You have been a great help Sir and you are obviously no rookie!

Thanks

David

davidbalmer
Contributor III
Contributor III
Author

Hi Ron,

I understand the use of Resident Tables.  What is troubling me are the [3] separate LOAD statements under your SPCOUNT: in the solution you have provided.

I thought that any LOAD statement had to be introduced under a corresponding new (Table:) name.  In your solution, this is not the case and I have not encountered this anywhere else.  Can you please explain how/why this is being done in my specific case?  Or, refer me to any reading that would cover such syntax.

Thanks again

David

campbellr
Creator
Creator

Hi David

The multiple loads are what Qlik folk refer to as "preceding loads". There is lots written about it so I won't go into the nitty gritty here. The short version is they work from the bottom up and allow you to build calculated fields at one level then refer to that field in the next level up.

To make the script a little more bullet proof it would probably be best to include an "order by" line in the resident load to sort the data by the acct field, as it is if you were to add a new line at the end that had the same acct as the first line it would treat it as a new acct.

What you were asking to do is simple in Excel world where there is intention to calculate values based on other rows of data. I've had trouble in the past with Qlik trying to produce a running total with multiple sort fields involved, it's possible but far more difficult than it should be.

Glad it does what you were after. If you can share a desired outcome I (or someone else) might be able to suggest another way to get there.

Ron

davidbalmer
Contributor III
Contributor III
Author

Ron, when I added 2 more records to ACCT 1212 in the InLine sample, the report becomes incorrect.  Specifically, if you run the following, the balance forward on line 4 of the 1212 ACCT is not correct.  Can you please take a look. 

Thanks David

tmp:

LOAD * INLINE [

    Acct, Balance, SalesPerson

    1212, 100, David

    1212, 100, Mike

    1212, 100, Lucy   

    1212, 100, Henry   

    1212, 100, Joshua

    1525, 325, Jack

    1525, 325, Bill

    1525, 325, Edgar

    1630, 100, Paul

];

NoConcatenate

SPCount:

Load

if(Acct=Previous(Acct),BalancePrev - AcctCountRT - 1, Balance -1) as BalanceClose

    ,if (Acct=Previous(Acct), Balance - AcctCountRT ,Balance) as Balance

    ,Acct

    ,SalesPerson

    ;

Load

    if (Acct=Previous(Acct), 1 + previous(AcctCount),0) as AcctCountRT

    ,*

    ;

Load

    Acct

    ,SalesPerson

    ,if(isnull(Previous(Balance)),Balance,Previous(Balance)) as BalancePrev

    ,Balance

    ,if (Acct=Previous(Acct),1,0) as AcctCount

Resident tmp;

Drop table tmp;

campbellr
Creator
Creator

Hi David

take 2, have tested this and it works for your data and includes a sorting to keep the entries with the same acct together.

So I've added in a row count to use in the calculation of how many salespeople exist in the list and use that to subtract from the balance.

The mapping load is to assign the row count of the first line for each account. I had tried this as a preceding load but the rowNo() function doesn't work with a preceding load.

tmp:

LOAD * INLINE [

    Acct, Balance, SalesPerson

    1212, 100, David

    1212, 100, Mike

    1212, 100, Lucy  

    1212, 100, Henry  

    1212, 100, Joshua

    1525, 325, Jack

    1525, 325, Bill

    1525, 325, Edgar

    1630, 100, Paul

];

Join (tmp)

Load 

*

    ,RowNo() as rowCount

Resident tmp

Order By Acct, SalesPerson;

MapFirstRow:

Mapping

Load

Acct,

    rowCount

Resident tmp

Order By Acct, rowCount;

NoConcatenate

SPCount:

Load   

     if (Acct=Previous(Acct),Balance - AcctSPNum,Balance) as Balance

    ,if (Acct=Previous(Acct),Balance - AcctSPNum - 1,Balance-1) as BalanceClose

    ,Acct

    ,SalesPerson;

Load

rowCount - AcctFirstRow as AcctSPNum

    ,*;

Load

    Acct

    ,ApplyMap('MapFirstRow',Acct) as AcctFirstRow

    ,SalesPerson

    ,if(isnull(Previous(Acct)),Acct,Previous(Acct)) as AcctPrevious

    ,Balance

    ,rowCount

Resident tmp

Order By Acct,rowCount;  

Drop table tmp;

davidbalmer
Contributor III
Contributor III
Author

Good Morning Ron:

Obviously, I have a lot to learn.  I am very grateful for your efforts and must "study" carefully what you have done.  I am of course adapting this InLine model to a bigger problem where the concept applies over hundreds of thousands of records.  The syntax is always a struggle for me, compounded by how and why one approach makes more sense over another.  I have purchased most of the QV books and been through a lot of examples on YouTube and am slowly grasping the basics.  The 'balance forward' calculation type of problem and your solution to it gives me a lot to think about and digest.  So now, and I admit this, I will adapt what you have supplied to my business problem without truly understanding all of its complete ramifications.  I may have to come back to you with a few questions specific to your solution when I get this thing underway.  Again, I am much obliged and think that this QV Community is one of the best things I have discovered.  Best regards David.

campbellr
Creator
Creator

Hi David

I'm happy to explain in more depth any of the bits that are causing concern. The preceding loads and ApplyMap() functions are two things I have found very useful recently. ApplyMap has  a distinct advantage over joining two tables in that it does not introduce duplication. It works like a vlookup in Excel in that it returns the value associated with the first match between the map and the data. Also the mapping table is automatically dropped after the load is complete.

davidbalmer
Contributor III
Contributor III
Author

Hi Ron:

I have applied your solution to the big picture and it works very well.  I do need to understand the how/why it works and will go through it as it is important to see the logic behind it all.  Right now, and with another post, I am having trouble with a Dynamic Calendar creation to view some of the data you have helped me with.  There is a great video on 'dynamic calendar' creation/usage at Selecting Arbitrary Date Ranges - YouTube.  I have implemented this approach in a few other projects and it works well.  But on this recent project and after I had it working with one specific date field, I tried to switch it over to another date field.  Now, it doesn't work and the Selections Box does not pick up the date ranges I am specifying.  I think that the "Trigger" function is at the root of this problem.  But strangely enough, and to try to eliminate any conflicts, I did a dummy creation of another .qvw and had no luck with it either. I can call anywhere in North America if you think an actual conversation would be useful.  I am in Toronto and if you would not mind I can call you at your convenience.  I have Team Viewer on my PC if that would be of any help.  Regardless, I sure have appreciated your help!