Is there an equivalent to the the HS.con function?

ChristianW
Valued Contributor

If I like to migrate a HFM rules file, is there an equivalent to the HS.con function?

1 ACCEPTED SOLUTION

ChristianW
Valued Contributor

Yes, there is, it is called setCell and it is a method of the databuffer class. It doesn't use a string as input, so it is a little different to use

resultDataBuffer.SetCell(si As SessionInfo, cell as DataCell, accumulateIfCellAlreadyEsists as boolean)

or

resultDataBuffer.SetCell(si As SessionInfo, cell as DataBufferCell, accumulateIfCellAlreadyEsists as boolean) 

The Onestream help is giving a similar example like this one for the whole process.

'Copy all "U2#Input:U3#Input" numbers for this dataUnit to the UD2 none Members and the UD3 member with the name "Target Member Name".
Dim destinationInfo As ExpressionDestinationInfo = api.Data.GetExpressionDestinationInfo("")
Dim sourceDataBuffer As DataBuffer = api.Data.GetDataBuffer(DataApiScriptMethodType.Calculate, "U2#Input:U3#Input", destinationInfo)
If Not sourceDataBuffer Is Nothing Then
    Dim resultDataBuffer As DataBuffer = New DataBuffer()
    For Each cell As DataBufferCell In sourceDataBuffer.DataBufferCells.Values
       If (Not cell.CellStatus.IsNoData) Then
          cell.DataBufferCellPk.UD2Id = DimConstants.None
          cell.DataBufferCellPk.UD3Id = api.Members.GetMemberId(dimtypeid.UD3, "Target Member Name")
          resultDataBuffer.SetCell(si, cell)
       End If
    Next
    api.Data.SetDataBuffer(resultDataBuffer, destinationInfo, True)
End If

 

View solution in original post

8 REPLIES 8

ChristianW
Valued Contributor

Yes, there is, it is called setCell and it is a method of the databuffer class. It doesn't use a string as input, so it is a little different to use

resultDataBuffer.SetCell(si As SessionInfo, cell as DataCell, accumulateIfCellAlreadyEsists as boolean)

or

resultDataBuffer.SetCell(si As SessionInfo, cell as DataBufferCell, accumulateIfCellAlreadyEsists as boolean) 

The Onestream help is giving a similar example like this one for the whole process.

'Copy all "U2#Input:U3#Input" numbers for this dataUnit to the UD2 none Members and the UD3 member with the name "Target Member Name".
Dim destinationInfo As ExpressionDestinationInfo = api.Data.GetExpressionDestinationInfo("")
Dim sourceDataBuffer As DataBuffer = api.Data.GetDataBuffer(DataApiScriptMethodType.Calculate, "U2#Input:U3#Input", destinationInfo)
If Not sourceDataBuffer Is Nothing Then
    Dim resultDataBuffer As DataBuffer = New DataBuffer()
    For Each cell As DataBufferCell In sourceDataBuffer.DataBufferCells.Values
       If (Not cell.CellStatus.IsNoData) Then
          cell.DataBufferCellPk.UD2Id = DimConstants.None
          cell.DataBufferCellPk.UD3Id = api.Members.GetMemberId(dimtypeid.UD3, "Target Member Name")
          resultDataBuffer.SetCell(si, cell)
       End If
    Next
    api.Data.SetDataBuffer(resultDataBuffer, destinationInfo, True)
End If

 

If you like to simplify the process, I would suggest, a sub-procedure to mimic the HS.con function

Public Sub Book(ByVal sourceCell As dataBufferCell, ByVal targetDataBuffer As DataBuffer, ByVal target As String, ByVal factor As Decimal)			
	Try
		'Create a DataBufferCellPk object for the target initialize it with the DataBufferCellPk of the source
		Dim targetCellPk 	As New DataBufferCellPk(sourceCell.DataBufferCellPk) 
		'Create a MemberScriptBuilder object for the target inizialize it with the target string
		Dim targetScript 	As New MemberScriptBuilder(target)
				
		'Loop all databuffer dimensions -> GetRightHandDimTypes
		For Each scriptDimType As DimType In DimType.GetRightHandDimTypes()
			Dim memberName As String = targetScript.MemberNames(scriptDimType.Name)
			'Test if the dimension exists in the target script
			If memberName <> "" Then 
				'If it exists override the source definition 
				targetCellPk.Item(scriptdimtype.Id) = api.Members.GetMemberId(scriptDimType.Id, memberName)
			End If	
		Next
				
		'Adjust the factor based On AccountType And Flow settings
		factor = factor * GetFactor(sourceCell.DataBufferCellPk, targetCellPk)
		Dim cellAmount As Decimal = factor * sourceCell.CellAmount

		'Creat a target cell as DataBufferCell using the targetcellPK, the cellAmount and the sourcecell's status
		Dim targetCell 	    As New DataBufferCell(targetCellPk, cellAmount, sourcecell.CellStatus)
				
		'Write it to the targetDataBuffer
		targetDataBuffer.SetCell(si, targetCell, True)

	Catch ex As Exception
				
		Throw ErrorHandler.LogWrite(si, New XFException(si, ex))
	End Try
		
End Sub

Private Function GetFactor (ByRef sourcecellPK As DataBufferCellPk, ByRef targetcellPK As DataBufferCellPk) As Decimal
	Dim factor As Decimal = 1
				
	'If both accounttypes not share the same sign (are both positive or both negative) multiply with -1
	If Not ((api.account.GetAccountType(targetcellPk.AccountId).IsAccountTypePositive = api.account.GetAccountType(sourcecellPK.AccountId).IsAccountTypePositive)) Then
		factor = factor*-1
	End If
	'If both flows not have the same switch sign setting multiply with -1
	If api.flow.SwitchSign(targetcellPk.flowid) Xor api.flow.SwitchSign(sourceCellPk.flowId) Then
		factor = factor*-1
	End If
	'Return the adjusted factor.
	Return factor			
End Function

I personally try to avoid working with strings, so I use something like the following function

 

 

Public Sub Book (ByRef oSourceCell As DataBufferCell, ByVal targetDataBuffer As DataBuffer, Optional ByVal iAccount As Integer = DimConstants.All, Optional ByVal iFlow As Integer = DimConstants.All, Optional ByVal iIC As Integer = DimConstants.All, Optional ByVal iOrigin As Integer = DimConstants.All, Optional ByVal iUD1 As Integer = DimConstants.All, Optional ByVal iUD2 As Integer = DimConstants.All, Optional ByVal iUD3 As Integer = DimConstants.All, Optional ByVal iUD4 As Integer = DimConstants.All, Optional ByVal iUD5 As Integer = DimConstants.All, Optional ByVal iUD6 As Integer = DimConstants.All, Optional ByVal iUD7 As Integer = DimConstants.All, Optional ByVal iUD8 As Integer = DimConstants.All, Optional ByVal dFactor As Decimal = 1) 
	Try		
		Dim oTargetCell As New DataBufferCell(oSourceCell)
					
		With oTargetCell.DataBufferCellPk
						
			If Not iAccount = DimConstants.All Then .AccountId = iAccount
			If Not iFlow = DimConstants.All Then .FlowId = iFlow
			If Not iIC = DimConstants.All Then .ICId = iIC
			If Not iOrigin = DimConstants.All Then .OriginId = iOrigin
			If Not iUD1 = DimConstants.All Then .UD1Id = iUD1
			If Not iUD2 = DimConstants.All Then .UD2Id = iUD2
			If Not iUD3 = DimConstants.All Then .UD3Id = iUD3
			If Not iUD4 = DimConstants.All Then .UD4Id = iUD4
			If Not iUD5 = DimConstants.All Then .UD5Id = iUD5
			If Not iUD6 = DimConstants.All Then .UD6Id = iUD6
			If Not iUD7 = DimConstants.All Then .UD7Id = iUD7
			If Not iUD8 = DimConstants.All Then .UD8Id = iUD8
							
		End With

		dFactor = dFactor * GetFactor(oSourceCell.DataBufferCellPk, oTargetCell.DataBufferCellPk)
		oTargetCell.CellAmount = dFactor * oSourceCell.CellAmount
					
		targetDataBuffer.SetCell(api.SI, oTargetCell, True)
			
	Catch ex As Exception
			
		Throw ErrorHandler.LogWrite(si, New XFException(si, ex))
	End Try

End Sub

 

 

Hi Christian,

is there a way to accumulate values in the destination intersection using the function api.Data.SetDataBuffer(resultDataBuffer, destinationInfo, True)

 

I have some BR where I need to cumulate values on a certain element but when I use the SetDataBuffer the rules saves only the last value of the sourceDataBuffer

 

Thanks in advance for the help.

Marcello

ChristianW
Valued Contributor

No, set databuffer is always overrideing the result, only setcell has the accumulate option.

But this is not a problem, if you start with an allready filled databuffer as a target databuffer, instead of an empty one, you obviously accumulate the result when writing back.

You can fill the target databuffer using the api.Data.GetDataBufferUsingFormula functions.

Great Post as always! I have a question, what if my target includes C#Elimination It seems like the code below does not set the C# to Elimination

		For Each scriptDimType As DimType In DimType.GetRightHandDimTypes()
			
			Dim memberName As String = targetScript.MemberNames(scriptDimType.Name)
			BRApi.ErrorLog.LogMessage(si, $"x: script dime type: {scriptDimType.Name} member name: {memberName} ")
			'Test if the dimension exists in the target script
			If memberName <> "" Then 
				'If it exists override the source definition 
				BRApi.ErrorLog.LogMessage(si, $"v: {api.Pov.Entity.Name} {memberName} ")
				targetCellPk.Item(scriptdimtype.Id) = api.Members.GetMemberId(scriptDimType.Id, memberName)

			End If	
		Next

ChristianW
Valued Contributor

Thank you Oscar

Consolidation isn‘t a databuffer dim, it is a dataunit dimension. The consolidation is controlled by the pov of the calculation.

But you have to be careful with the origin dimension, an elimination only works, if the origin is elimination as well.

cheers

Christian

Oscar
Contributor

Thank You Chrsitian! Still analyzing how best to handle the special treatment (calculation) of these Equity Accounts, but your comment is right on point!