Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Analyzing Data with Power BI and Power Pivot for Excel (Alberto Ferrari, Marco Russo) (z-lib.org).pdf
Скачиваний:
11
Добавлен:
14.08.2022
Размер:
18.87 Mб
Скачать

Chapter 11. Working with multiple currencies

In this chapter, we will analyze some models that have in common the need to handle multiple sales in multiple currencies. As you will learn, whenever you need to handle multiple currencies, the number of problems increases by a lot. In fact, there are many decisions you will need to make to accommodate for multiple currencies in terms of the size of the model, flexibility, and performance.

We first introduce the problem of currency conversion, showing the challenges and problems you might face when developing models in different scenarios. Then, as in previous chapters, we build some examples of data models involving currency conversion. There are different ways of modeling the same scenario, and we analyze them to identify the pros and cons of each.

Understanding different scenarios

As mentioned, currency conversion hides some complexity that is already in the definition of the problem. In fact, a large company is likely to receive and to pay money in different currencies, and, as we all know, the value of a currency changes over time. This makes it important to convert from one currency to another to compare volumes of money in different currencies. Let us focus on a simple example. Suppose Contoso received EUR 100 on January 20 from a customer. How do we convert this value into USD, given that USD is the main currency of Contoso? There are the following ways:

You immediately transform EUR to USD when the money is received

This is the simplest way to handle currency conversion because basically, you have a single currency to handle.

You deposit EUR into a current account and then use it to pay in EUR when needed This makes it hard to build reports in different currencies because the value of sales changes every day, depending on the current value of the currency.

You deposit EUR into a current account and perform a currency conversion at the end of the month (or at any given point in time except the original transaction) In this case, you must handle multiple, varying currencies for a limited amount of time.

Note

There might be policies that make any one of these three basic options impossible. The reason we cited these three different ways is not to give you an exhaustive list of options. Instead we wanted to show at least three legitimate ways of managing currency conversion.

By defining the point in time when conversion should happen, you are thinking about how to store the data. But, once the data is stored, you might want to build reports on top of it. If you perform conversion in the main currency, then the reporting problems are somewhat mitigated. However, if you want to be able to report in different currencies, then you might need to store transactions in EUR and report them in USD, Yen, or any other currency. This makes it necessary to be able to perform online conversion—that is, conversion of currency in real-time when the query is executed.

When it comes to currency conversion, you need to spend a lot of time understanding exactly what the requirements are because the resulting data models are very different. There is no single model that can handle all the possible scenarios. Moreover, from a performance point of view, currency conversion is very challenging. This is probably the main reason you should try to keep it as simple as possible, by avoiding handling models that are more complex than strictly needed.

Multiple source currencies, single reporting currency

Suppose the source data contains orders in different currencies, and you want to produce a report containing information with a single type of currency. For example, you collect orders in EUR, USD, and other currencies, but, to be able to compare sales, you want to convert them all to a single currency.

Let us start with a quick look at the model we use for this scenario, shown in Figure 11-1. Sales has a relationship with Currency, which indicates that each sale is recorded with the currency in which it happened.

FIGURE 11-1 In this model, sales are recorded with different currencies and sliced by currency.

The first question with such a model is, what is the meaning of Unit Price, Unit Discount, and all the other currency columns stored in Sales? If you saved the values in the original currency, as is likely the case, then you are in trouble as soon as you author a simple calculation like the sales amount. If you use a formula like the following one, the result might not be what you expected:

Click here to view code image

Sales Amount := SUMX ( Sales, Sales[Quantity] * Sales[Net Price] )

We used the same formula for Sales Amount in most of this book, but when used with currencies, it stops working. Figure 11-2 shows the result of a simple report based on this formula, where the totals at the column level make no sense. This is because they are summing values in different currencies, which leads to useless numbers.

FIGURE 11-2 In this report, the total at the column level is summing different currencies.

The report correctly shows the values and the row totals because they refer to a single currency. When it comes to the column level, however, these numbers are a nonsense. You simply cannot sum together Euro, Danish Krone, and US Dollar unless you perform a conversion and define a target currency to use for the sum.

Because of the presence of data in different currencies, you should protect these measures from showing meaningless values. Use the HASONEVALUE function to guarantee that the result is returned if and only if a single currency has been selected. In the following code, we cover this first need:

Click here to view code image

Sales Amount := IF (

HASONEVALUE ( Currency[Currency] ),

SUMX ( Sales, Sales[Quantity] * Sales[Net Price]

)

Using this new measure, the report loses the total on the columns, where the sum should not be displayed, as shown in Figure 11-3.

FIGURE 11-3 By protecting the code, you avoid showing the totals when they cannot be computed.

Even without the totals at the column level, this report is not very useful. A report is generally used to compare numbers, but the values shown in this table cannot simply be compared. It would be even worse to build a chart on top of this data because, at that point, it would seem natural to do a comparison. If you need to compare these values, then you need to either use the currency as a filter and then slice by some other column or normalize all the values to a common currency.

The easiest way to do this is to create a calculated column in the Sales table that computes the amount in the currency you want to use for your reports. For now, let us make things simple and imagine that we want to produce reports in USD. You can create a calculated column in Sales that computes the rate to USD of the current day for the current currency. In the demo, we used the following code, which you might need to adapt for your scenario:

Click here to view code image

RateToUsd =

LOOKUPVALUE(

ExchangeRate[AverageRate], ExchangeRate[CurrencyKey], Sales[CurrencyKey], ExchangeRate[DateKey], RELATED ( 'Date'[Date] )

)

Once RateToUSD is in place, you can use it to compute Sales Amount USD by simply multiplying the value of the sales amount by the exchange rate. Thus, Sales Amount USD is computed by the following DAX code:

Click here to view code image

Sales Amount USD = SUMX (

Sales,

Sales[Quantity] * DIVIDE ( Sales[Net Price], Sal

)

With the measure, you can now show a report that lets you compare sales in different years and currencies with meaningful values, as shown in Figure 11-4.

FIGURE 11-4 When values are converted to the report currency, you can safely compare them and produce totals.

This technique is pretty simple to implement. The logic about the exact date when the conversion should happen is configured in the calculated column. If you have different needs, you can change that definition and obtain the right result. For example, if you need to get the exchange rate of the day after, you can simply modify the LOOKUPVALUE function to search for that exchange rate. The main limitation of this technique is that it works fine if you have a single currency for the reports. If you have many of them, you will need a separate measure (and calculated column) for each of them.

Note

The Sales Amount USD measure has a format string that shows a dollar symbol in front of it. The format string of a measure is static, meaning you cannot change it dynamically. The technique of using a separate measure for each reporting currency is widely adopted, and

we suggest you follow it to make the user experience better.

Before leaving this first scenario, it is worth noting that the number it computes is not completely correct. In fact, if you compare Figure 11-4 and Figure 11-3, you will see that the value for 2009 is lower in Figure 11-4. (This is evident if you look at the US Dollar row.) When complex calculations are involved, as in this case, spotting errors is not trivial. In fact, the problem is evident in the US Dollar row, which should always convert one-to-one. However, it is also present in all the other currencies, although much less evident. Double-checking your values is always a good practice. So where is the issue? If you look at the data in the Sales table, you will notice several hundreds of rows that have a blank RateToUsd column, as shown in Figure 11-5. Here, we sorted by RateToUsd to show the blank rows first.

FIGURE 11-5 The RateToUsd column is empty for several rows.

The problem here is that the exchange rate is not available for all the dates, so the LOOKUPVALUE function does not return any number. As with many other scenarios related to currency conversion, you need to define what to do in such a case. If the conversion rate for a given day is not available, then the numbers reported are wrong, and you cannot afford such a scenario. In the following code, we decided to take the latest conversion ratio if the current day’s rate is not available:

Click here to view code image