Forum Discussion

PhilB's avatar
PhilB
New Contributor III
2 years ago

How do I get the correct Cell Status on a data buffer cell?

I have a process that builds a data buffer using Data Buffer Cell Loop logic. I need to check the cell status on each record and perform certain actions based on the status. Specifically, I want to make sure all 12 Account-Type dimensions are referencing a base member and correct them if they aren't.

However, I'm not getting the correct Cell Status when the cell is in a data buffer. For example this code creates two data cells and logs their status. (In this case, I'm looking at DataCells, but the behavior is identical on DataBufferCell objects). Metadata is from GolfStream.:

 

Dim baseMemberFilter As String = "A#50200:O#Import:U2#None:U8#Test"
Dim cellPk As DataCellPk = api.Data.ParseDataCellScript(baseMemberFilter)
Dim cell As DataCell = api.Data.CreateDataCellObject(cellPk, True, 100, False, False)
api.LogMessage("Base UD2 GetMemberScript: " & cell.DataCellPk.GetMemberScript(api))
api.LogMessage("Base UD2 CellStatus.UD2HasChildren: " & cell.CellStatus.UD2HasChildren)

Dim parentMemberFilter As String = "A#50200:O#Import:U2#Clubs:U8#Test"
Dim cellPk2 As DataCellPk = api.Data.ParseDataCellScript(parentMemberFilter)
Dim cell2 As DataCell = api.Data.CreateDataCellObject(cellPk2, True, 100, False, False)
api.LogMessage("Parent UD2 GetMemberScript: " & cell2.DataCellPk.GetMemberScript(api))
api.LogMessage("Parent UD2 UD2HasChildren: " & cell2.CellStatus.UD2HasChildren)

 

Because the first data cell references UD2#None, you would expect .CellStatus.UD2HasChildren to return FALSE (which it does).  Because the second data cell references UD2#Clubs (a parent), you would expect .CellStatus.UD2HasChildren to return TRUE, but it doesn't. It also returns FALSE. Below is a screenshot of the log file. Other CellStatus properties (.ReadyOnly, .AreRightHandMembersBase, etc.) are also incorrect, I just chose to highlight the UDXHasChildren because it's the easiest to visualize.

So, two questions:

  1. How do I get OneStream to return a correct cell status for a DataCell or DataBufferCell?
  2. If it's not possible to get a correct status, what is the most efficient way to determine if a specific DataCell contains any parent members? I'm sure I could parse the member filter into it's 12 dimensions and check each member individually, but that is likely much too slow for the volumes we have.

Thanks, Phil B

 

  • Steven's avatar
    Steven
    Contributor II

    For Each sourceCell As DataBufferCell In sourceDataBuffer.DataBufferCells.Values
    BRApi.ErrorLog.LogMessage(si, sourceCell.CellStatus.ToString)  

     

    'This will fill up your errorlog and is not reccomended for large databuffers 

     

    Archetype Consulting

  • JackLacava's avatar
    JackLacava
    Honored Contributor

    I suspect the problem is that you're creating datacell objects from scratch, rather than retrieving them. Try using GetDataCell instead, and it should give you cells that are as expected.

    This said, this all smells of an anti-pattern. You shouldn't need to start from cells to build buffers; instead, you retrieve buffers and only go to cell level if strictly necessary, getting them from the buffers. If you build a buffer from scratch, you typically populate it with cells that are copies of cells you retrieved in some other buffer. Let OneStream sweat on the details of object creation.

  • PhilB's avatar
    PhilB
    New Contributor III

    Hi Jack,

    Thanks for your feedback. I just wanted to clarify a few things that I think were misinterpreted:

     - I'm only creating the datacell objects from scratch as an example to demonstrate the fundamental issue (status is incorrect) for this forum post. As I mentioned at the top of the post, the actual code is in a typical Data Buffer Cell Loop structure. So, it's pulling a data buffer, looping thru the records in that data buffer, modifying the contents of those records, and writing out the result data buffer. Both the data buffer definition and modifications are driven by end-user input. But the fundamental issue is the same - within the contents of the result data buffer, the cell status doesn't reflect the cell's updated metadata.

     - I can't do a GetDataCell, because this is inside of a calculation. The data record doesn't exist in the database until the calculation writes out the result data buffer to the database. So, it's a catch-22: I can't pull a GetDataCell until the cell is written to the database, but I can't write to the database until I do the correct calculation.

     

    Sorry if the example caused confusion, but I wanted to focus on the core issue - how/why cell status works(or doesn't work) the way it does - not on the structure of the rule.

    Thanks,

     

    • JackLacava's avatar
      JackLacava
      Honored Contributor

      There is never going to be a cell in a buffer that targets a parent for Account-like dimensions, because there is never a record created for parents in those dimensions. So all those PKs will always reflect base elements for those dimensions. When you use those to build synthetic elements in memory, the system doesn't go back to the database to check if the new Pk is valid or anything, it's just an abstract representation that you built (effectively, a dictionary of some sort); anything you don't explicitly set, won't be refreshed for you. So those flags will always stay at False.

      If you want to retrieve representations of actual data and datastructures, you have to do a "Get" call of some sort. With those, if you explicitly target parents in Account-like dimensions, the system will calculate values in memory and should give you a synthetic representation that has the correct flags.

      For the record, if you are doing this because you're trying to "roll your own rollups", use the Convert* functions instead, they will do the work for you.