You are on page 1of 21

1 Scenario

SAP Business Planning and Consolidation provides standard support for multicurrency translation and reporting. The default configuration expects all data to be loaded in the local currency (LC) and then translated into one or more common reporting currencies. However, if a significant portion of the LC data is also in the main reporting currency used, there are alternative configurations available that can dramatically improve currency conversion time and save disk space in the relational database. This guide will go through the basic currency translation configuration and processes along with the changes required to implement such a partial translation configuration.

2 Introduction
It is quite common to find multicurrency financial models where a large portion of the data is already in the desired reporting currency. For example, a US based manufacturing company may have facilities located in Mexico and Canada which require data to be loaded in their local currencies for internal reporting purposes. However, for management and external reporting purposes financial statements are prepared only in US Dollars (the reporting currency). Assume that 1,000,000 records are loaded into their BPC system each month and that 10% of the data comes from the Canadian facilities and 12% comes from the Mexican facilities. In the standard configuration, all 1,000,000 records would be loaded to the reporting currency of LC. Then currency translation would be run to convert the data into the reporting currency of USD producing an additional 1,000,000 records in the fact table for a total of 2,000,000 records. However, 780,000 of these records have the same value in LC as in USD. It would be more desirable in this case to only convert the 220,000 records that need to be translated so that only 1,220,000 records reside in the fact table. In this guide, we will go through how the standard currency translation process functions within BPC, how to modify it to only translate limited data, and the implications and design considerations for other components within the application. This process can only be used in models where there is a single reporting currency. If all data in the application must be converted into more than one reporting currency, the solution in this guide will not be of benefit. For illustrative purposes, the sample application ApShell will be used to go through the configuration process. The screen shots, code examples, and step by step process shown in this guide will be from 5.x BPC. However, the basic concepts and configuration process is the same in the 4.x releases of BPC.

3 Standard Currency Translation

The currency translation process (FXTrans) makes use of an application (typically called Rate) to store the currency exchange rates in and one or more applications which hold the financial data that requires translation. The currency translation process reads in the local currency (LC) records from the financial application, looks up the corresponding currency translation rate in the rate application, and generates a new record in the financial application for the same dimensional intersections as the original record except for the reporting currency value. The original LC records remain unchanged. Using this process, data that comes into the application either through manual data entry or through bulk loading is always and only loaded to the reporting currency of LC or then translated to one or more desired reporting currencies.


Dimensions and Properties

First we will look at the dimensions within ApShell for the Finance and Rate applications and discuss the specific dimensions and properties that are used for currency translation. In this model, the Finance application is the main user application and the Rate application is where currency exchange rate data is stored.

Dimension Name Account Category DataSrc Entity IntCo RptCurrency Time InputCurrency Rate RateSrc

Caption Account Category Data Source Entity Intercompany Report Currency Time Input Currency Currency Rate Rate Source

Dimension Type Account Category DataSrc Entity Intercompany Currency Time Currency Account Entity
Table 1

Finance Application X X X X X X X

Rate Application X


Dimension Name Category Entity RptCurrency

Time Input Currency

Rate RateSrc

Description Identifies the scenario or classification of data (e.g. Actual, Budget, Forecast) Typically the primary units of the organizational structures (e.g. departments, cost center, plants) The currency or currencies that financial reporting is done in. These are the currencies that data will be translated to for reporting purposes. In addition, the LC currency is required in this dimension to hold un-translated data. Fiscal or Calendar time These are the local currencies that data is entered into the application from. This is not the same as the reporting currencies. For example, if a US company has locations in Mexico, Canada, and the US, the input currencies would be MXN, CAD and USD. However if data is only converted to USD, the reporting currencies would only be LC and USD. The type of exchange rate. (e.g. average, period end, historical) Rates are entered to the RateInput member and logic is used to derive the RateCalc value which is used to perform the currency translation.
Table 2

The first thing to notice is there are two shared dimensions (Category and Time) between the two applications. This means when exchange rates are entered they are specific to a category and time period. The most common reason for currency translation to not work is forgetting to enter the exchange rates into the corresponding category and time periods. Another common question is why is the Rate dimension an account type dimension and RateSrc an entity type dimension? The short answer is because all applications are required to have an account type and entity type dimension (along with time and category types). There is no intrinsic meaning to the types used in this case. There is actually a relationship between the Account dimension in the Finance application and the Rate dimension in the currency translation process but it has nothing to do with the dimension types but rather how theyre used in the process. If you are creating a new rate application after the main application(s) have been created, you should use the dimension names and types that are listed here to ensure that the currency translation process will work without modification and for general consistency to aid support staff. All other relationships besides time and category between the applications are done through properties. The key properties that are used for the basic currency translation process are listed in Table 3. 2

Dimension Name Account

Property RateType

Usage / Notes
Identifies the rate that is used to convert the account for FXTrans. P&L accounts translate at the average rate for the period and BS accounts translate at the period end rate. However, there can be additional rates if there are items that have some fixed historical rate. The values entered in the property must be the valid ID of a member in the RATE dimension. If accounts are not translated (e.g. volumes, head count) then the property is left blank. Also, FXTrans only occurs on base level members so the property can be omitted on parent level members but is typically filled in for purposes such as report filtering. This identifies the local currency of the member. The value must correspond to the ID of a member of the InputCurrency dimension. By default, the entity type dimension is assumed to determine the currency of the record since in a typical model it corresponds to a physical location. If the entity type dimension is not the dimension that uniquely associates a record with a currency then the default currency translation process would have to be modified. A Y indicates that the local currency is also a reporting currency. Value is either Multipy or Divide. This is used by default logic in the rate application to derive the RATECALC value which is used to actually perform the currency translation. This particular property is not used to control the currency translation process and has no intrinsic meaning in the context of the dimension. However, it is a required property on account type dimensions and controls whether the values accumulate across time or not and whether the values in the fact table are signed positively or negatively. So for reporting purposes, the type of AST is used so the value does not accumulate across time and so the underlying values are stored as positive number in the fact tables.



InputCurrency InputCurrency Rate

Reporting MD Acctype

Rate InputCurrency

Group Reporting

The value of FX Rate must be on each rate that is to be included in the currency translation process. All members of the dimension other than LC would have a flag value of Y
Table 3

3.2 Logic to Perform FXTrans There are two standard calculation processes available within BPC to perform FX translation: script logic and business rules. Script logic uses the proprietary scripting language of BPC to code the translation rules. These rules can be customized as needed to support application specific needs. The business rules are encrypted SQL stored procedures that are supplied to perform various tasks one of which is currency translation. The source code for the business rules is not published code and the rules cannot be modified. In a standard configuration, both processes produce the exact same numerical results. In general, the business rule will run faster than the script logic but the time difference can vary depending on the amount of data and hardware resources.


Script Logic

The script logic file that runs currency translation is FXTrans and is accessed through the BPC Administration interface. Script logic is application specific so you will need to drill into the individual applications to access the code.

Figure 1

Depending on when and how currency translation was setup in an existing application you may either have reference to the translation code as in this example or the underlying code which we will discuss shortly. In this example, the line *SYSLIB MultiCurrencyTrans.LGL is referencing or including the underlying translation code from the system library. To access the underlying code, you will have to directly open the system library file using notepad or another text editor. The files are located in on the file server in the \Webfolders\AppsetName\SystemLibrary\Logic Library folder. The referenced file contains the logic shown in Code 1. The translation process first determines what rates and currencies need to be processed. It then clears any previous data that was generated by earlier FXTrans processes for the same category and time scope as the current run. Next, the process goes to the rate application and looks-up the correct currency translation rates. Finally using the rate type property on the account dimension and the currency property on the entity dimension, each record is translated into the reporting currency selected. If the rate type property is NOTRANS then no record will be generated in the reporting currency. If the rate type is a valid member of the Rate dimension, then the record will be converted at the appropriate rate. Otherwise, if the rate type is blank (or invalid) a record will be generated in the reporting currency with the same value as the local currency value. This is typically used for non financial data such as volumes or headcount so that the statistical data and the financial data are together to make reporting easier. Note that the code uses variables (e.g. CURRENCYDIM) that are defined in the included system constants file. The code in Code 2 is Code 1 with the comments removed and the variables replaced with the underlying values. This is the final executed code.

//================================================================================= // MULTI-CURRENCY TRANSLATION LOGIC //================================================================================= //____________________________________________________________________ // filter the appropriate currencies and rates //____________________________________________________________________ *SELECT(%REPORTING_CURRENCIES%, "[ID]", "CURRENCYDIM", "[REPORTING] = 'Y'") *SELECT(%FX_RATES%, "[ID]", "RATEACCOUNTDIM", "[GROUP] = 'FX RATE'") //____________________________________________________________________ // set the appropriate region to clear //(all reporting currencies) //____________________________________________________________________ *CLEAR_DESTINATION *DESTINATION CURRENCYDIM=%REPORTING_CURRENCIES% //____________________________________________________________________ // load the rates from the RATE cube //____________________________________________________________________ *LOOKUP RATEAPP *DIM RATEENTITYDIM="RATEENTITYMBR" *DIM RATEACCOUNTDIM=ACCOUNTDIM.RATETYPE *DIM SOURCECURR:INPUTCURRENCYDIM=ENTITYDIM.CURRENCY *FOR %CURR%=%REPORTING_CURRENCIES% *DIM %CURR%:INPUTCURRENCYDIM="%CURR%" *NEXT *ENDLOOKUP //____________________________________________________________________ // define the translation rule //____________________________________________________________________ *WHEN ACCOUNTDIM.RATETYPE *IS "NOTRANS" // skip *IS %FX_RATES% // translate *FOR %CURR%=%REPORTING_CURRENCIES% *REC(EXPRESSION=ROUND(%VALUE% /(LOOKUP(SOURCECURR)/LOOKUP(%CURR%)),2),CURRENCYDIM="%CURR%") *NEXT *ELSE // take as is *FOR %CURR%=%REPORTING_CURRENCIES% *REC(CURRENCYDIM="%CURR%") *NEXT *ENDWHEN

Code 1


As discussed earlier, there is script logic in the Rate application that converts the rates entered by the user (RateInput) to the appropriate factor to perform the currency translation. The code is shown below (Code 3) with all underlying variables substituted for clarity. Based on whether the input currency is entered as a divisor rate or multiplier rate, the appropriate calculated rate (RateCalc) is derived. All the rates in ApShell are setup as divisor rates. *XDIM_MEMBERSET RATE=AVG,END *XDIM_MEMBERSET INPUTCURRENCY= USD,CAD,MXN *XDIM_MEMBER RATESRC=RATEINPUT *WHEN INPUTCURRENCY.MD *IS "D" *REC(EXPRESSION=ROUND(1/%VALUE%,6),RATESRC="RATECALC") *ELSE *REC(RATESRC="RATECALC") *ENDWHEN *CLEAR_DESTINATION *DESTINATION RATESRC=RATECALC
Code 3

Currency Translation Example Account dimension (partial members and properties) ID Description RateType Cash Cash END AR Accounts Receivable END ExtSales External Sales AVG COGS Cost of Goods Sold AVG FTE Full-time equivalent heads Temp_Calc Calculation temp account NOTRANS
Table 4

Entity dimension (partial members and properties) ID Description Currency NE_SALES Northeast Sales office USD SE_SALES Southeast Sales office USD Montreal_Plant_1 Montreal Mfg Plant 1 CAD Veracruz_Plant_8 Veracruz Mfg Plant 8 MXN
Table 5

Category Actual Actual Actual Actual Actual Actual Actual Actual

Time 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC

Rate Application Fact table InputCurrency Rate RateSrc CAD AVG RateInput CAD END RateInput MXN AVG RateInput MXN END RateInput CAD AVG RateCalc CAD END RateCalc MXN AVG RateCalc MXN END RateCalc
Table 6

SignedData 1.0015 0.9820 10.8631 10.9235 0.998502 1.018330 0.092055 0.091546

Finance Application Fact table (assume no FXTrans has been run)

Account Cash AR ExtSales COGS FTE Temp_Calc Cash Category Actual Actual Actual Actual Actual Actual Actual DataSrc GL_Feed GL_Feed GL_Feed GL_Feed GL_Feed CALC GL_Feed Entity NE_SALES SE_SALES Montreal_Plant_1 Veracruz_Plant_8 Montreal_Plant_1 Montreal_Plant_1 Veracruz_Plant_8 IntCo Non_InterCo Non_InterCo Non_InterCo Non_InterCo Non_InterCo Non_InterCo Non_InterCo Table 7 RptCurrency LC LC LC LC LC LC LC Time 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC SignedData 5000 1300 8900 4200 80 445 200

Fact table records and member properties (other dimensions excluded for clarity)
Account Account. RateType Entity Entity. Currency Category Time Exchange Rate based on properties found in Rate Application 1 1 0.998502 0.092055 NULL NULL 0.091546 Calculated Translation Rate (Source Rate / USD Rate) 1 1 0.998502 0.092055

Cash AR ExtSales COGS FTE Temp_Calc Cash


NE_SALES SE_SALES Montreal_Plant_1 Veracruz_Plant_8 Montreal_Plant_1 Montreal_Plant_1 Veracruz_Plant_8


Actual Actual Actual Actual Actual Actual Actual Table 8

2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC


Table 8 shows the properties used in the script logic to determine the appropriate rate to associate with each record. The value in column 8 is the value from the rate application lookup. This is the RateCalc member (shaded records in table 6) which was derived by logic in the rate application at the time the exchange rates were entered. The value in column 9 is calculated by the FXTrans script logic which is then multiplied by the record in the fact table to calculate the translated value for the new record. Table 9 shows the fact table in the Finance application after FXTrans has run. Note that no record is produced for Temp_Calc where as one is for FTE based on their RateType properties.

Finance Application Fact table (after FXTrans)

Account Cash AR ExtSales COGS FTE Temp_Calc Cash Cash AR ExtSales COGS FTE Cash Category Actual Actual Actual Actual Actual Actual Actual Actual Actual Actual Actual Actual Actual DataSrc GL_Feed GL_Feed GL_Feed GL_Feed GL_Feed CALC GL_Feed GL_Feed GL_Feed GL_Feed GL_Feed GL_Feed GL_Feed Entity NE_SALES SE_SALES Montreal_Plant_1 Veracruz_Plant_8 Montreal_Plant_1 Montreal_Plant_1 Veracruz_Plant_8 NE_SALES SE_SALES Montreal_Plant_1 Veracruz_Plant_8 Montreal_Plant_1 Veracruz_Plant_8 IntCo Non_InterCo Non_InterCo Non_InterCo Non_InterCo Non_InterCo Non_InterCo Non_InterCo Non_InterCo Non_InterCo Non_InterCo Non_InterCo Non_InterCo Non_InterCo Table 9 RptCurrency LC LC LC LC LC LC LC USD USD USD USD USD USD Time 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC 2007.DEC SignedData 5000 1300 8900 4200 80 445 200 5000 1300 8886.67 386.31 80 18.31

The script based logic is executed either on demand through data manager or automatically as part of default logic depending on the business processes and system requirements of the individual installation. Figure 2 shows executing the process on demand using the standard SSIS package provided. Note that this SSIS package specifically runs the script logic named FXTrans. If you modify the underlying code, the best practice is to create a new script file with your modified code and then simply modify FXTrans to include the new code. This avoids the possibility of losing your code modifications during an upgrade and avoids the need to create a new dedicated SSIS package to run your code.

Figure 2


Business Rules

Business rules are SQL stored procedures that are provided with the BPC product. The stored procedures are encrypted and cannot be viewed or modified during implementation. There are a number of business rule installed with the product one of which is currency translation. All the dimensions and properties used for the script logic FX translation are used for the business rules FX translation. To run the stored procedure, a call is made using a script logic file. The basic call would be:

Using the call above, all records within the scope of execution would have currency translation performed as described in the script logic currency translation process. Typically, this call would be placed in the FXTrans script logic file replacing the call to the script logic currency conversion process. This allows the code to be run on demand with the standard SSIS package as well as being included in other script logic files.

This call does not use any values from the business rules parameter table so no configuration there is required. There is a process in the current conversion business rules that can be configured to perform a similar limited currency conversion process. The details of that and the other options available in the parameter table are in the Administration help file under the business rules configuration section. The main disadvantage of this approach is that it makes use of dummy LC entity members and currency translation data is written to a separate member in the entity dimension. That is, if you have an entity in Mexico (e.g. Mexico_City) you would have one member (Mexico_City_LC) where data is loaded in LC. Then when currency translation is performed, the reporting currency data would be written to a separate member (Mexico_City_USD) in the entity dimension to separate out the LC from the translated data. This process would work fine for very small numbers of foreign currency entities but would become difficult to manage if there were 50 or 100 entities in a larger model that needed to have currency translation performed. Also having separate members for LC and non-LC data can make navigating the hierarchy for reporting purposes more challenging.

4 Modifying for limited FXTrans

4.1 Step by Step Process The modifications needed to implement limited translation are to add an additional property to the entity type dimension on which your currency translation is defined and modifying the script logic rules to limit which entity members are processed. As of BPC 5.1 SP1, the business rules stored procedures do not support the limited translation process. Therefore, to implement this change does require the use of the script logic version of FXTrans. However, BPC 5.1 SP3 is targeted to support the process described. When implemented, the structure changes described would need to be made as described but no additional changes should be required. IMPORTANT: Before you begin these modifications, be sure ALL data in your existing application has had currency conversion run. Also, read through the entire guide BEFORE beginning the modifications so that you have a clear understand of all the required changes and have an appropriate implementation plan.
4.1.1 Structure Changes

1. The first change will be to add the property IS_CONVERTED with a size of 1 in the entity dimension. The property does not need to be in the application for the FXTrans to work. You can optionally add it to be InApp if you wish to be able to do reporting within BPC on the property. 2. Then select the Modify Dimension Property to create the property in the application.

1 2

Figure 3

3. When the dimension has completed processing, choose Maintain Dimension Members to open the member sheet. The new column with your property will be the last column in the property list on the right. 4. You now need to populate the property with a value of Y on each member that you wish to translate. Ideally this would be only base-level members since they are the only ones that have data in the fact table. One approach is to use an Excel formula to fill in the property. This approach does put the property in on base and non-base members but it shouldnt make any difference. The formula below [=IF(F2<>USD,Y,)] would put a Y in all non-USD entities and a blank space in the USD entities.

Figure 4


Figure 5

5. After you have copied down the formula, do a copy and paste special-values to convert the formula to plain text. 6. Validate and process the dimension. When this completes put the application back on line.
4.1.2 Logic Changes

1. Next you need to make a copy of the currency translation logic into a new logic file with a different name so that the file cannot be accidently overwritten. This can be done in the system library or the code can be put into a logic file in the application. If there are a number of applications that will share the same logic, the library is a better option. If there is only one or two and you dont mind putting the code into each application, creating a script file has the advantages of making it obvious you are using customized FXTrans logic and make accessing the code easier as there is no interface to modify the system library files. For this guide, we will create and new script logic file in the application.

Figure 6


Figure 7

Figure 8

2. Now copy the contents of the MultiCurrencyTrans.LGL from the logic library file into the new script logic file. If you choose to keep the file in the system library, then make a copy of the file and


rename it in the same folder.

Figure 9

3. Now we begin making the logic modifications. First modify the logic to include the system constants. Originally this was done in the FXTrans code itself but to validate this logic file, the constants will need to be included here.

Figure 10

4. Now we need to limit the members of the entity dimension that are cleared at the beginning of the process. We only want to clear data for entities which we will be performing currency translation on based on the [IS_CONVERTED] property. 13

Figure 11

5. Now put the filter list in the clear destination statement

Figure 12


6. Next we want to filter the records that are processed to only be entities that are translated.

Figure 13

7. Finally, add a *COMMIT statement to the end of the code so this logic file is a complete code segment.


8. The final code (with comments removed) is:




Code 4

9. Now, to avoid having to modify the SSIS package that runs the logic file, we will simply modify the FXTrans logic file to call the newly created logic. The figure 14 is if logic is in the script logic file and figure 15 is if the code is in the system library. Note the difference in file extensions depending on where the file is stored.


Figure 14

Figure 15



Data modifications

1. Now that you have modified the structure and logic, your application will no longer convert data in your reporting currency from LC so this data can be deleted to free up disk space and improve overall application performance. IMPORTANT: These steps will be deleting data from the relational database so be sure you have a verified backup of your SQL database before proceeding. 2. Perform an incremental optimization with compressions to get all records into one fact table and eliminate duplicate records to make the deletion process go a quickly as possible. This process can take a number of hours to run depending on the number of records in the fact table and the hardware resources available. Be sure to plan an adequate maintenance window. Also, the transaction log will grow quite large so it should be shrunk after this process completes back to a normal size for your environment. 3. Using query analyzer, execute the following query. This will delete all LC data from the fact table for entities that will not be translated. Be sure you have correctly set and verified the IS_CONVERTED property on the entity dimension. This will have to be repeated for each application in your application set that is being modified. Note that {FINANCE} in the table name is the name of the particular application. Delete From tblFactFINANCE where RptCurrency = LC and Entity in (Select [ID] from mbrEntity where IS_CONVERTED <> Y) 4. Run an incremental optimization on each application that you have cleared data for so that the Analysis Service application will be updated. 5. You will need to modify any existing data ETL processes so that data in your reporting currency (USD in the guide example) is loaded directly to the reporting currency and not to LC. For all records that are not in the reporting currency, they will continue to be loaded to LC. The ETL process rules must match the IS_CONVERTED flag in your application to get accurate currency conversion. 4.2 Other considerations 1. If you have other script logic in your application, you will need to modify it to explicitly process records in your reporting currency. By default, logic only executes on LC. This can be done with *XDIM_ADDMEMBERSET RPTCURRENCY=USD statement. Depending on the rules of the script logic, you may have to modify the code to specifically run calculations on LC only for translated entities and separate calculations on non-LC your reporting currency for non-translated entities. 2. If you application is a planning system or otherwise has manual data entry screens, then these will need to be modified so that the screen sends data to the appropriate currency based on the current entity. This would have to be done on each input schedule and can be accomplished by reading the entity property using BPC functions and some basic Excel formulas. The example in Figure 16 reads the IS_CONVERTED property from the current entity. If the property is Y, then data is written to LC otherwise it is written to the reporting currency.


Figure 16

3. If there are custom data manipulation processes that have been implemented (e.g. custom stored procedures or SSIS packages) then these will need to be reviewed and possibly modified to deal with the differences in where data is loaded.