- Deprecated function: Use of "static" in callables is deprecated in Drupal\user\Entity\Role::postLoad() (line 172 of core/modules/user/src/Entity/Role.php).
Drupal\user\Entity\Role::postLoad(Object, Array) (Line: 423)
Drupal\Core\Entity\EntityStorageBase->postLoad(Array) (Line: 353)
Drupal\Core\Entity\EntityStorageBase->loadMultiple(Array) (Line: 16)
Drupal\user\RoleStorage->isPermissionInRoles('access site in maintenance mode', Array) (Line: 112)
Drupal\Core\Session\UserSession->hasPermission('access site in maintenance mode') (Line: 105)
Drupal\Core\Session\AccountProxy->hasPermission('access site in maintenance mode') (Line: 83)
Drupal\redirect\RedirectChecker->canRedirect(Object) (Line: 120)
Drupal\redirect\EventSubscriber\RedirectRequestSubscriber->onKernelRequestCheckRedirect(Object, 'kernel.request', Object)
call_user_func(Array, Object, 'kernel.request', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.request') (Line: 145)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\mysql\Driver\Database\mysql\Select::$alterMetaData is deprecated in Drupal\Core\Database\Query\Select->addMetaData() (line 178 of core/lib/Drupal/Core/Database/Query/Select.php).
Drupal\Core\Database\Query\Select->addMetaData('entity_type', 'file') (Line: 115)
Drupal\Core\Entity\Query\Sql\Query->prepare() (Line: 80)
Drupal\Core\Entity\Query\Sql\Query->execute() (Line: 640)
Drupal\Core\Entity\EntityStorageBase->loadByProperties(Array) (Line: 63)
Drupal\Core\Entity\EntityRepository->loadEntityByUuid('file', 'insert-max_800_px-48c7d6c1-4870-4d74-b165-caba177a4d17') (Line: 95)
Drupal\editor\Plugin\Filter\EditorFileReference->process('Un escenario frecuente es aquel en el que queremos calcular el total acumulado, incluyendo todos los datos hasta una cierta fecha y no solo los implicados en el contexto de filtro actual. Por ejemplo, si suponemos la existencia de una tabla de ventas Sales que contiene una columna Amount con la cifra de ventas, podríamos definir una medida que calculase la suma de esta columna con la siguiente expresión DAX:
Sales = SUM(Sales[Amount])
Lógicamente, esta medida se va a adaptar al contexto de filtro, por lo que si la llevamos a una matriz en la que se esté desagregando las ventas por año:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_01.png"></a>
...vemos que, para cada año, la cifra de ventas mostrada incluye solo las ventas de dicho año.
Lo que querríamos sería que, en cada evaluación de la medida, el período temporal considerado comenzase el primer día para que el hubo ventas (supongamos que el 1 de enero de 2015) y se extendiese hasta la última fecha del "período actual". Por ejemplo, en la cifra correspondiente al año 2018 el período actual es el correspondiente a los 365 días de dicho año. Pues bien, para el cálculo del acumulado para dicho año querríamos que se considerase el período comprendido entre el 1 de enero de 2015 y el 31 de diciembre de 2018. Es decir, escrito en pseudo-código:
Accumulated sales =
CALCULATE(
[Sales],
Período entre la primera fecha disponible y la última fecha del contexto actual
)
El período en cuestión puede calcularse usando la función <a href="/es/dax/function/datesbetween">DATESBETWEEN</a> que devuelve el conjunto de fechas entre dos dadas. Si el calendario está contenido en la tabla Calendar, tendríamos, por lo tanto, que codificar la siguiente medida:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
Primera fecha disponible,
Última fecha del contexto actual
)
)
Ahora bien, es el cálculo de esas dos fechas lo que resulta más complejo, pues queremos que la primera fecha ("<em>Primera fecha disponible</em>") sea absoluta y haga referencia a la primera fecha disponible en el calendario, mientras que la segunda ("<em>Última fecha del contexto actual</em>") queremos que se adapte al contexto.
Para la obtención de la primera fecha disponible en el calendario deberemos asegurarnos de que no se están aplicando filtros al mismo, para lo que podemos usar la función <a href="/es/dax/function/all">ALL</a> (lo que va a devolver una tabla). Y para la extracción de la primera fecha disponible de dicha tabla no podemos usar la función <a href="/es/dax/function/min">MIN</a> pues ésta exige una columna como argumento, de forma que tendremos que usar la función <a href="/es/dax/function/firstdate">FIRSTDATE</a>, que sí acepta una tabla como argumento y devuelve otra tabla (con la fecha más antigua disponible), tabla que podemos pasar a la función <a href="/es/dax/function/calculate">CALCULATE</a> como argumento de filtro:
FIRSTDATE(ALL(Sales[Order Date]))
Para el cálculo de la última fecha del contexto actual no tenemos más que utilizar la función <a href="/es/dax/function/max">MAX</a> pasando como argumento la columna temporal que está desagregando nuestro objeto visual: la columna 'Calendar'[Date]. Es decir, la última fecha del contexto actual vendría dada por:
MAX('Calendar'[Date])
Es decir, la expresión
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
...va a devolver el conjunto de fechas del calendario entre la más antigua disponible y la última implicada en el contexto actual. Podemos escribir, por lo tanto, la medida que devuelve las ventas acumuladas:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
)
Si quisiéramos utilizar variables para hacer más legible el código, podríamos crear dos variables, __firstdate y __lastDate conteniendo las dos fechas implicadas en el código anterior:
Accumulated sales =
VAR __firstDate = FIRSTDATE(ALL(Sales[Order Date]))
VAR __lastDate = MAX('Calendar'[Date])
RETURN
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
__firstDate,
__lastDate
)
)
Ahora, si llevamos la medida anterior a nuestra matriz, comprobamos que se están acumulando las ventas tal y como queríamos:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_02.png"></a>
Y, por supuesto, si mostramos la matriz desagregada por cualquier otro nivel de nuestra jerarquía temporal, por trimestres, por ejemplo, el cálculo de las ventas acumuladas sigue realizándose correctamente:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_03.png"></a>', 'es') (Line: 118)
Drupal\filter\Element\ProcessedText::preRenderText(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 88)
__TwigTemplate_a7d6005c89ae729617b9a0c2bccb1776->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 46)
__TwigTemplate_804f7948456cfe20e11a34c43439c7c2->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 43)
__TwigTemplate_bd990293b89f3b78c69fe0ee2f7828b5->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/contrib/classy/templates/field/field--text-with-summary.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('field', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 446)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 74)
__TwigTemplate_94047fbdba6937b76a4479dfa1763452->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/custom/yg_aesthetic/templates/node.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('node', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 242)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 235)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.view') (Line: 174)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\mysql\Driver\Database\mysql\Select::$alterTags is deprecated in Drupal\Core\Database\Query\Select->addTag() (line 149 of core/lib/Drupal/Core/Database/Query/Select.php).
Drupal\Core\Database\Query\Select->addTag('entity_query') (Line: 147)
Drupal\Core\Entity\Query\Sql\Query->prepare() (Line: 80)
Drupal\Core\Entity\Query\Sql\Query->execute() (Line: 640)
Drupal\Core\Entity\EntityStorageBase->loadByProperties(Array) (Line: 63)
Drupal\Core\Entity\EntityRepository->loadEntityByUuid('file', 'insert-max_800_px-48c7d6c1-4870-4d74-b165-caba177a4d17') (Line: 95)
Drupal\editor\Plugin\Filter\EditorFileReference->process('Un escenario frecuente es aquel en el que queremos calcular el total acumulado, incluyendo todos los datos hasta una cierta fecha y no solo los implicados en el contexto de filtro actual. Por ejemplo, si suponemos la existencia de una tabla de ventas Sales que contiene una columna Amount con la cifra de ventas, podríamos definir una medida que calculase la suma de esta columna con la siguiente expresión DAX:
Sales = SUM(Sales[Amount])
Lógicamente, esta medida se va a adaptar al contexto de filtro, por lo que si la llevamos a una matriz en la que se esté desagregando las ventas por año:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_01.png"></a>
...vemos que, para cada año, la cifra de ventas mostrada incluye solo las ventas de dicho año.
Lo que querríamos sería que, en cada evaluación de la medida, el período temporal considerado comenzase el primer día para que el hubo ventas (supongamos que el 1 de enero de 2015) y se extendiese hasta la última fecha del "período actual". Por ejemplo, en la cifra correspondiente al año 2018 el período actual es el correspondiente a los 365 días de dicho año. Pues bien, para el cálculo del acumulado para dicho año querríamos que se considerase el período comprendido entre el 1 de enero de 2015 y el 31 de diciembre de 2018. Es decir, escrito en pseudo-código:
Accumulated sales =
CALCULATE(
[Sales],
Período entre la primera fecha disponible y la última fecha del contexto actual
)
El período en cuestión puede calcularse usando la función <a href="/es/dax/function/datesbetween">DATESBETWEEN</a> que devuelve el conjunto de fechas entre dos dadas. Si el calendario está contenido en la tabla Calendar, tendríamos, por lo tanto, que codificar la siguiente medida:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
Primera fecha disponible,
Última fecha del contexto actual
)
)
Ahora bien, es el cálculo de esas dos fechas lo que resulta más complejo, pues queremos que la primera fecha ("<em>Primera fecha disponible</em>") sea absoluta y haga referencia a la primera fecha disponible en el calendario, mientras que la segunda ("<em>Última fecha del contexto actual</em>") queremos que se adapte al contexto.
Para la obtención de la primera fecha disponible en el calendario deberemos asegurarnos de que no se están aplicando filtros al mismo, para lo que podemos usar la función <a href="/es/dax/function/all">ALL</a> (lo que va a devolver una tabla). Y para la extracción de la primera fecha disponible de dicha tabla no podemos usar la función <a href="/es/dax/function/min">MIN</a> pues ésta exige una columna como argumento, de forma que tendremos que usar la función <a href="/es/dax/function/firstdate">FIRSTDATE</a>, que sí acepta una tabla como argumento y devuelve otra tabla (con la fecha más antigua disponible), tabla que podemos pasar a la función <a href="/es/dax/function/calculate">CALCULATE</a> como argumento de filtro:
FIRSTDATE(ALL(Sales[Order Date]))
Para el cálculo de la última fecha del contexto actual no tenemos más que utilizar la función <a href="/es/dax/function/max">MAX</a> pasando como argumento la columna temporal que está desagregando nuestro objeto visual: la columna 'Calendar'[Date]. Es decir, la última fecha del contexto actual vendría dada por:
MAX('Calendar'[Date])
Es decir, la expresión
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
...va a devolver el conjunto de fechas del calendario entre la más antigua disponible y la última implicada en el contexto actual. Podemos escribir, por lo tanto, la medida que devuelve las ventas acumuladas:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
)
Si quisiéramos utilizar variables para hacer más legible el código, podríamos crear dos variables, __firstdate y __lastDate conteniendo las dos fechas implicadas en el código anterior:
Accumulated sales =
VAR __firstDate = FIRSTDATE(ALL(Sales[Order Date]))
VAR __lastDate = MAX('Calendar'[Date])
RETURN
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
__firstDate,
__lastDate
)
)
Ahora, si llevamos la medida anterior a nuestra matriz, comprobamos que se están acumulando las ventas tal y como queríamos:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_02.png"></a>
Y, por supuesto, si mostramos la matriz desagregada por cualquier otro nivel de nuestra jerarquía temporal, por trimestres, por ejemplo, el cálculo de las ventas acumuladas sigue realizándose correctamente:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_03.png"></a>', 'es') (Line: 118)
Drupal\filter\Element\ProcessedText::preRenderText(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 88)
__TwigTemplate_a7d6005c89ae729617b9a0c2bccb1776->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 46)
__TwigTemplate_804f7948456cfe20e11a34c43439c7c2->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 43)
__TwigTemplate_bd990293b89f3b78c69fe0ee2f7828b5->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/contrib/classy/templates/field/field--text-with-summary.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('field', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 446)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 74)
__TwigTemplate_94047fbdba6937b76a4479dfa1763452->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/custom/yg_aesthetic/templates/node.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('node', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 242)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 235)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.view') (Line: 174)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\mysql\Driver\Database\mysql\Select::$alterMetaData is deprecated in Drupal\Core\Database\Query\Select->addMetaData() (line 178 of core/lib/Drupal/Core/Database/Query/Select.php).
Drupal\Core\Database\Query\Select->addMetaData('entity_type', 'file') (Line: 115)
Drupal\Core\Entity\Query\Sql\Query->prepare() (Line: 80)
Drupal\Core\Entity\Query\Sql\Query->execute() (Line: 640)
Drupal\Core\Entity\EntityStorageBase->loadByProperties(Array) (Line: 63)
Drupal\Core\Entity\EntityRepository->loadEntityByUuid('file', 'insert-max_800_px-48c7d6c1-4870-4d74-b165-caba177a4d17') (Line: 124)
Drupal\editor\Plugin\Filter\EditorFileReference->process('Un escenario frecuente es aquel en el que queremos calcular el total acumulado, incluyendo todos los datos hasta una cierta fecha y no solo los implicados en el contexto de filtro actual. Por ejemplo, si suponemos la existencia de una tabla de ventas Sales que contiene una columna Amount con la cifra de ventas, podríamos definir una medida que calculase la suma de esta columna con la siguiente expresión DAX:
Sales = SUM(Sales[Amount])
Lógicamente, esta medida se va a adaptar al contexto de filtro, por lo que si la llevamos a una matriz en la que se esté desagregando las ventas por año:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_01.png"></a>
...vemos que, para cada año, la cifra de ventas mostrada incluye solo las ventas de dicho año.
Lo que querríamos sería que, en cada evaluación de la medida, el período temporal considerado comenzase el primer día para que el hubo ventas (supongamos que el 1 de enero de 2015) y se extendiese hasta la última fecha del "período actual". Por ejemplo, en la cifra correspondiente al año 2018 el período actual es el correspondiente a los 365 días de dicho año. Pues bien, para el cálculo del acumulado para dicho año querríamos que se considerase el período comprendido entre el 1 de enero de 2015 y el 31 de diciembre de 2018. Es decir, escrito en pseudo-código:
Accumulated sales =
CALCULATE(
[Sales],
Período entre la primera fecha disponible y la última fecha del contexto actual
)
El período en cuestión puede calcularse usando la función <a href="/es/dax/function/datesbetween">DATESBETWEEN</a> que devuelve el conjunto de fechas entre dos dadas. Si el calendario está contenido en la tabla Calendar, tendríamos, por lo tanto, que codificar la siguiente medida:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
Primera fecha disponible,
Última fecha del contexto actual
)
)
Ahora bien, es el cálculo de esas dos fechas lo que resulta más complejo, pues queremos que la primera fecha ("<em>Primera fecha disponible</em>") sea absoluta y haga referencia a la primera fecha disponible en el calendario, mientras que la segunda ("<em>Última fecha del contexto actual</em>") queremos que se adapte al contexto.
Para la obtención de la primera fecha disponible en el calendario deberemos asegurarnos de que no se están aplicando filtros al mismo, para lo que podemos usar la función <a href="/es/dax/function/all">ALL</a> (lo que va a devolver una tabla). Y para la extracción de la primera fecha disponible de dicha tabla no podemos usar la función <a href="/es/dax/function/min">MIN</a> pues ésta exige una columna como argumento, de forma que tendremos que usar la función <a href="/es/dax/function/firstdate">FIRSTDATE</a>, que sí acepta una tabla como argumento y devuelve otra tabla (con la fecha más antigua disponible), tabla que podemos pasar a la función <a href="/es/dax/function/calculate">CALCULATE</a> como argumento de filtro:
FIRSTDATE(ALL(Sales[Order Date]))
Para el cálculo de la última fecha del contexto actual no tenemos más que utilizar la función <a href="/es/dax/function/max">MAX</a> pasando como argumento la columna temporal que está desagregando nuestro objeto visual: la columna 'Calendar'[Date]. Es decir, la última fecha del contexto actual vendría dada por:
MAX('Calendar'[Date])
Es decir, la expresión
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
...va a devolver el conjunto de fechas del calendario entre la más antigua disponible y la última implicada en el contexto actual. Podemos escribir, por lo tanto, la medida que devuelve las ventas acumuladas:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
)
Si quisiéramos utilizar variables para hacer más legible el código, podríamos crear dos variables, __firstdate y __lastDate conteniendo las dos fechas implicadas en el código anterior:
Accumulated sales =
VAR __firstDate = FIRSTDATE(ALL(Sales[Order Date]))
VAR __lastDate = MAX('Calendar'[Date])
RETURN
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
__firstDate,
__lastDate
)
)
Ahora, si llevamos la medida anterior a nuestra matriz, comprobamos que se están acumulando las ventas tal y como queríamos:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_02.png"></a>
Y, por supuesto, si mostramos la matriz desagregada por cualquier otro nivel de nuestra jerarquía temporal, por trimestres, por ejemplo, el cálculo de las ventas acumuladas sigue realizándose correctamente:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_03.png"></a>', 'es') (Line: 118)
Drupal\filter\Element\ProcessedText::preRenderText(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 88)
__TwigTemplate_a7d6005c89ae729617b9a0c2bccb1776->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 46)
__TwigTemplate_804f7948456cfe20e11a34c43439c7c2->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 43)
__TwigTemplate_bd990293b89f3b78c69fe0ee2f7828b5->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/contrib/classy/templates/field/field--text-with-summary.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('field', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 446)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 74)
__TwigTemplate_94047fbdba6937b76a4479dfa1763452->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/custom/yg_aesthetic/templates/node.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('node', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 242)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 235)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.view') (Line: 174)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\mysql\Driver\Database\mysql\Select::$alterTags is deprecated in Drupal\Core\Database\Query\Select->addTag() (line 149 of core/lib/Drupal/Core/Database/Query/Select.php).
Drupal\Core\Database\Query\Select->addTag('entity_query') (Line: 147)
Drupal\Core\Entity\Query\Sql\Query->prepare() (Line: 80)
Drupal\Core\Entity\Query\Sql\Query->execute() (Line: 640)
Drupal\Core\Entity\EntityStorageBase->loadByProperties(Array) (Line: 63)
Drupal\Core\Entity\EntityRepository->loadEntityByUuid('file', 'insert-max_800_px-48c7d6c1-4870-4d74-b165-caba177a4d17') (Line: 124)
Drupal\editor\Plugin\Filter\EditorFileReference->process('Un escenario frecuente es aquel en el que queremos calcular el total acumulado, incluyendo todos los datos hasta una cierta fecha y no solo los implicados en el contexto de filtro actual. Por ejemplo, si suponemos la existencia de una tabla de ventas Sales que contiene una columna Amount con la cifra de ventas, podríamos definir una medida que calculase la suma de esta columna con la siguiente expresión DAX:
Sales = SUM(Sales[Amount])
Lógicamente, esta medida se va a adaptar al contexto de filtro, por lo que si la llevamos a una matriz en la que se esté desagregando las ventas por año:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_01.png"></a>
...vemos que, para cada año, la cifra de ventas mostrada incluye solo las ventas de dicho año.
Lo que querríamos sería que, en cada evaluación de la medida, el período temporal considerado comenzase el primer día para que el hubo ventas (supongamos que el 1 de enero de 2015) y se extendiese hasta la última fecha del "período actual". Por ejemplo, en la cifra correspondiente al año 2018 el período actual es el correspondiente a los 365 días de dicho año. Pues bien, para el cálculo del acumulado para dicho año querríamos que se considerase el período comprendido entre el 1 de enero de 2015 y el 31 de diciembre de 2018. Es decir, escrito en pseudo-código:
Accumulated sales =
CALCULATE(
[Sales],
Período entre la primera fecha disponible y la última fecha del contexto actual
)
El período en cuestión puede calcularse usando la función <a href="/es/dax/function/datesbetween">DATESBETWEEN</a> que devuelve el conjunto de fechas entre dos dadas. Si el calendario está contenido en la tabla Calendar, tendríamos, por lo tanto, que codificar la siguiente medida:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
Primera fecha disponible,
Última fecha del contexto actual
)
)
Ahora bien, es el cálculo de esas dos fechas lo que resulta más complejo, pues queremos que la primera fecha ("<em>Primera fecha disponible</em>") sea absoluta y haga referencia a la primera fecha disponible en el calendario, mientras que la segunda ("<em>Última fecha del contexto actual</em>") queremos que se adapte al contexto.
Para la obtención de la primera fecha disponible en el calendario deberemos asegurarnos de que no se están aplicando filtros al mismo, para lo que podemos usar la función <a href="/es/dax/function/all">ALL</a> (lo que va a devolver una tabla). Y para la extracción de la primera fecha disponible de dicha tabla no podemos usar la función <a href="/es/dax/function/min">MIN</a> pues ésta exige una columna como argumento, de forma que tendremos que usar la función <a href="/es/dax/function/firstdate">FIRSTDATE</a>, que sí acepta una tabla como argumento y devuelve otra tabla (con la fecha más antigua disponible), tabla que podemos pasar a la función <a href="/es/dax/function/calculate">CALCULATE</a> como argumento de filtro:
FIRSTDATE(ALL(Sales[Order Date]))
Para el cálculo de la última fecha del contexto actual no tenemos más que utilizar la función <a href="/es/dax/function/max">MAX</a> pasando como argumento la columna temporal que está desagregando nuestro objeto visual: la columna 'Calendar'[Date]. Es decir, la última fecha del contexto actual vendría dada por:
MAX('Calendar'[Date])
Es decir, la expresión
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
...va a devolver el conjunto de fechas del calendario entre la más antigua disponible y la última implicada en el contexto actual. Podemos escribir, por lo tanto, la medida que devuelve las ventas acumuladas:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
)
Si quisiéramos utilizar variables para hacer más legible el código, podríamos crear dos variables, __firstdate y __lastDate conteniendo las dos fechas implicadas en el código anterior:
Accumulated sales =
VAR __firstDate = FIRSTDATE(ALL(Sales[Order Date]))
VAR __lastDate = MAX('Calendar'[Date])
RETURN
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
__firstDate,
__lastDate
)
)
Ahora, si llevamos la medida anterior a nuestra matriz, comprobamos que se están acumulando las ventas tal y como queríamos:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_02.png"></a>
Y, por supuesto, si mostramos la matriz desagregada por cualquier otro nivel de nuestra jerarquía temporal, por trimestres, por ejemplo, el cálculo de las ventas acumuladas sigue realizándose correctamente:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_03.png"></a>', 'es') (Line: 118)
Drupal\filter\Element\ProcessedText::preRenderText(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 88)
__TwigTemplate_a7d6005c89ae729617b9a0c2bccb1776->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 46)
__TwigTemplate_804f7948456cfe20e11a34c43439c7c2->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 43)
__TwigTemplate_bd990293b89f3b78c69fe0ee2f7828b5->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/contrib/classy/templates/field/field--text-with-summary.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('field', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 446)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 74)
__TwigTemplate_94047fbdba6937b76a4479dfa1763452->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/custom/yg_aesthetic/templates/node.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('node', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 242)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 235)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.view') (Line: 174)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\mysql\Driver\Database\mysql\Select::$alterMetaData is deprecated in Drupal\Core\Database\Query\Select->addMetaData() (line 178 of core/lib/Drupal/Core/Database/Query/Select.php).
Drupal\Core\Database\Query\Select->addMetaData('entity_type', 'file') (Line: 115)
Drupal\Core\Entity\Query\Sql\Query->prepare() (Line: 80)
Drupal\Core\Entity\Query\Sql\Query->execute() (Line: 640)
Drupal\Core\Entity\EntityStorageBase->loadByProperties(Array) (Line: 63)
Drupal\Core\Entity\EntityRepository->loadEntityByUuid('file', 'insert-max_800_px-dab86cbb-c629-45d8-9afa-ee730c81aa40') (Line: 95)
Drupal\editor\Plugin\Filter\EditorFileReference->process('Un escenario frecuente es aquel en el que queremos calcular el total acumulado, incluyendo todos los datos hasta una cierta fecha y no solo los implicados en el contexto de filtro actual. Por ejemplo, si suponemos la existencia de una tabla de ventas Sales que contiene una columna Amount con la cifra de ventas, podríamos definir una medida que calculase la suma de esta columna con la siguiente expresión DAX:
Sales = SUM(Sales[Amount])
Lógicamente, esta medida se va a adaptar al contexto de filtro, por lo que si la llevamos a una matriz en la que se esté desagregando las ventas por año:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_01.png"></a>
...vemos que, para cada año, la cifra de ventas mostrada incluye solo las ventas de dicho año.
Lo que querríamos sería que, en cada evaluación de la medida, el período temporal considerado comenzase el primer día para que el hubo ventas (supongamos que el 1 de enero de 2015) y se extendiese hasta la última fecha del "período actual". Por ejemplo, en la cifra correspondiente al año 2018 el período actual es el correspondiente a los 365 días de dicho año. Pues bien, para el cálculo del acumulado para dicho año querríamos que se considerase el período comprendido entre el 1 de enero de 2015 y el 31 de diciembre de 2018. Es decir, escrito en pseudo-código:
Accumulated sales =
CALCULATE(
[Sales],
Período entre la primera fecha disponible y la última fecha del contexto actual
)
El período en cuestión puede calcularse usando la función <a href="/es/dax/function/datesbetween">DATESBETWEEN</a> que devuelve el conjunto de fechas entre dos dadas. Si el calendario está contenido en la tabla Calendar, tendríamos, por lo tanto, que codificar la siguiente medida:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
Primera fecha disponible,
Última fecha del contexto actual
)
)
Ahora bien, es el cálculo de esas dos fechas lo que resulta más complejo, pues queremos que la primera fecha ("<em>Primera fecha disponible</em>") sea absoluta y haga referencia a la primera fecha disponible en el calendario, mientras que la segunda ("<em>Última fecha del contexto actual</em>") queremos que se adapte al contexto.
Para la obtención de la primera fecha disponible en el calendario deberemos asegurarnos de que no se están aplicando filtros al mismo, para lo que podemos usar la función <a href="/es/dax/function/all">ALL</a> (lo que va a devolver una tabla). Y para la extracción de la primera fecha disponible de dicha tabla no podemos usar la función <a href="/es/dax/function/min">MIN</a> pues ésta exige una columna como argumento, de forma que tendremos que usar la función <a href="/es/dax/function/firstdate">FIRSTDATE</a>, que sí acepta una tabla como argumento y devuelve otra tabla (con la fecha más antigua disponible), tabla que podemos pasar a la función <a href="/es/dax/function/calculate">CALCULATE</a> como argumento de filtro:
FIRSTDATE(ALL(Sales[Order Date]))
Para el cálculo de la última fecha del contexto actual no tenemos más que utilizar la función <a href="/es/dax/function/max">MAX</a> pasando como argumento la columna temporal que está desagregando nuestro objeto visual: la columna 'Calendar'[Date]. Es decir, la última fecha del contexto actual vendría dada por:
MAX('Calendar'[Date])
Es decir, la expresión
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
...va a devolver el conjunto de fechas del calendario entre la más antigua disponible y la última implicada en el contexto actual. Podemos escribir, por lo tanto, la medida que devuelve las ventas acumuladas:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
)
Si quisiéramos utilizar variables para hacer más legible el código, podríamos crear dos variables, __firstdate y __lastDate conteniendo las dos fechas implicadas en el código anterior:
Accumulated sales =
VAR __firstDate = FIRSTDATE(ALL(Sales[Order Date]))
VAR __lastDate = MAX('Calendar'[Date])
RETURN
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
__firstDate,
__lastDate
)
)
Ahora, si llevamos la medida anterior a nuestra matriz, comprobamos que se están acumulando las ventas tal y como queríamos:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_02.png"></a>
Y, por supuesto, si mostramos la matriz desagregada por cualquier otro nivel de nuestra jerarquía temporal, por trimestres, por ejemplo, el cálculo de las ventas acumuladas sigue realizándose correctamente:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_03.png"></a>', 'es') (Line: 118)
Drupal\filter\Element\ProcessedText::preRenderText(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 88)
__TwigTemplate_a7d6005c89ae729617b9a0c2bccb1776->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 46)
__TwigTemplate_804f7948456cfe20e11a34c43439c7c2->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 43)
__TwigTemplate_bd990293b89f3b78c69fe0ee2f7828b5->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/contrib/classy/templates/field/field--text-with-summary.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('field', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 446)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 74)
__TwigTemplate_94047fbdba6937b76a4479dfa1763452->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/custom/yg_aesthetic/templates/node.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('node', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 242)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 235)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.view') (Line: 174)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\mysql\Driver\Database\mysql\Select::$alterTags is deprecated in Drupal\Core\Database\Query\Select->addTag() (line 149 of core/lib/Drupal/Core/Database/Query/Select.php).
Drupal\Core\Database\Query\Select->addTag('entity_query') (Line: 147)
Drupal\Core\Entity\Query\Sql\Query->prepare() (Line: 80)
Drupal\Core\Entity\Query\Sql\Query->execute() (Line: 640)
Drupal\Core\Entity\EntityStorageBase->loadByProperties(Array) (Line: 63)
Drupal\Core\Entity\EntityRepository->loadEntityByUuid('file', 'insert-max_800_px-dab86cbb-c629-45d8-9afa-ee730c81aa40') (Line: 95)
Drupal\editor\Plugin\Filter\EditorFileReference->process('Un escenario frecuente es aquel en el que queremos calcular el total acumulado, incluyendo todos los datos hasta una cierta fecha y no solo los implicados en el contexto de filtro actual. Por ejemplo, si suponemos la existencia de una tabla de ventas Sales que contiene una columna Amount con la cifra de ventas, podríamos definir una medida que calculase la suma de esta columna con la siguiente expresión DAX:
Sales = SUM(Sales[Amount])
Lógicamente, esta medida se va a adaptar al contexto de filtro, por lo que si la llevamos a una matriz en la que se esté desagregando las ventas por año:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_01.png"></a>
...vemos que, para cada año, la cifra de ventas mostrada incluye solo las ventas de dicho año.
Lo que querríamos sería que, en cada evaluación de la medida, el período temporal considerado comenzase el primer día para que el hubo ventas (supongamos que el 1 de enero de 2015) y se extendiese hasta la última fecha del "período actual". Por ejemplo, en la cifra correspondiente al año 2018 el período actual es el correspondiente a los 365 días de dicho año. Pues bien, para el cálculo del acumulado para dicho año querríamos que se considerase el período comprendido entre el 1 de enero de 2015 y el 31 de diciembre de 2018. Es decir, escrito en pseudo-código:
Accumulated sales =
CALCULATE(
[Sales],
Período entre la primera fecha disponible y la última fecha del contexto actual
)
El período en cuestión puede calcularse usando la función <a href="/es/dax/function/datesbetween">DATESBETWEEN</a> que devuelve el conjunto de fechas entre dos dadas. Si el calendario está contenido en la tabla Calendar, tendríamos, por lo tanto, que codificar la siguiente medida:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
Primera fecha disponible,
Última fecha del contexto actual
)
)
Ahora bien, es el cálculo de esas dos fechas lo que resulta más complejo, pues queremos que la primera fecha ("<em>Primera fecha disponible</em>") sea absoluta y haga referencia a la primera fecha disponible en el calendario, mientras que la segunda ("<em>Última fecha del contexto actual</em>") queremos que se adapte al contexto.
Para la obtención de la primera fecha disponible en el calendario deberemos asegurarnos de que no se están aplicando filtros al mismo, para lo que podemos usar la función <a href="/es/dax/function/all">ALL</a> (lo que va a devolver una tabla). Y para la extracción de la primera fecha disponible de dicha tabla no podemos usar la función <a href="/es/dax/function/min">MIN</a> pues ésta exige una columna como argumento, de forma que tendremos que usar la función <a href="/es/dax/function/firstdate">FIRSTDATE</a>, que sí acepta una tabla como argumento y devuelve otra tabla (con la fecha más antigua disponible), tabla que podemos pasar a la función <a href="/es/dax/function/calculate">CALCULATE</a> como argumento de filtro:
FIRSTDATE(ALL(Sales[Order Date]))
Para el cálculo de la última fecha del contexto actual no tenemos más que utilizar la función <a href="/es/dax/function/max">MAX</a> pasando como argumento la columna temporal que está desagregando nuestro objeto visual: la columna 'Calendar'[Date]. Es decir, la última fecha del contexto actual vendría dada por:
MAX('Calendar'[Date])
Es decir, la expresión
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
...va a devolver el conjunto de fechas del calendario entre la más antigua disponible y la última implicada en el contexto actual. Podemos escribir, por lo tanto, la medida que devuelve las ventas acumuladas:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
)
Si quisiéramos utilizar variables para hacer más legible el código, podríamos crear dos variables, __firstdate y __lastDate conteniendo las dos fechas implicadas en el código anterior:
Accumulated sales =
VAR __firstDate = FIRSTDATE(ALL(Sales[Order Date]))
VAR __lastDate = MAX('Calendar'[Date])
RETURN
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
__firstDate,
__lastDate
)
)
Ahora, si llevamos la medida anterior a nuestra matriz, comprobamos que se están acumulando las ventas tal y como queríamos:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_02.png"></a>
Y, por supuesto, si mostramos la matriz desagregada por cualquier otro nivel de nuestra jerarquía temporal, por trimestres, por ejemplo, el cálculo de las ventas acumuladas sigue realizándose correctamente:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_03.png"></a>', 'es') (Line: 118)
Drupal\filter\Element\ProcessedText::preRenderText(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 88)
__TwigTemplate_a7d6005c89ae729617b9a0c2bccb1776->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 46)
__TwigTemplate_804f7948456cfe20e11a34c43439c7c2->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 43)
__TwigTemplate_bd990293b89f3b78c69fe0ee2f7828b5->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/contrib/classy/templates/field/field--text-with-summary.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('field', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 446)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 74)
__TwigTemplate_94047fbdba6937b76a4479dfa1763452->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/custom/yg_aesthetic/templates/node.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('node', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 242)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 235)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.view') (Line: 174)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\mysql\Driver\Database\mysql\Select::$alterMetaData is deprecated in Drupal\Core\Database\Query\Select->addMetaData() (line 178 of core/lib/Drupal/Core/Database/Query/Select.php).
Drupal\Core\Database\Query\Select->addMetaData('entity_type', 'file') (Line: 115)
Drupal\Core\Entity\Query\Sql\Query->prepare() (Line: 80)
Drupal\Core\Entity\Query\Sql\Query->execute() (Line: 640)
Drupal\Core\Entity\EntityStorageBase->loadByProperties(Array) (Line: 63)
Drupal\Core\Entity\EntityRepository->loadEntityByUuid('file', 'insert-max_800_px-dab86cbb-c629-45d8-9afa-ee730c81aa40') (Line: 124)
Drupal\editor\Plugin\Filter\EditorFileReference->process('Un escenario frecuente es aquel en el que queremos calcular el total acumulado, incluyendo todos los datos hasta una cierta fecha y no solo los implicados en el contexto de filtro actual. Por ejemplo, si suponemos la existencia de una tabla de ventas Sales que contiene una columna Amount con la cifra de ventas, podríamos definir una medida que calculase la suma de esta columna con la siguiente expresión DAX:
Sales = SUM(Sales[Amount])
Lógicamente, esta medida se va a adaptar al contexto de filtro, por lo que si la llevamos a una matriz en la que se esté desagregando las ventas por año:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_01.png"></a>
...vemos que, para cada año, la cifra de ventas mostrada incluye solo las ventas de dicho año.
Lo que querríamos sería que, en cada evaluación de la medida, el período temporal considerado comenzase el primer día para que el hubo ventas (supongamos que el 1 de enero de 2015) y se extendiese hasta la última fecha del "período actual". Por ejemplo, en la cifra correspondiente al año 2018 el período actual es el correspondiente a los 365 días de dicho año. Pues bien, para el cálculo del acumulado para dicho año querríamos que se considerase el período comprendido entre el 1 de enero de 2015 y el 31 de diciembre de 2018. Es decir, escrito en pseudo-código:
Accumulated sales =
CALCULATE(
[Sales],
Período entre la primera fecha disponible y la última fecha del contexto actual
)
El período en cuestión puede calcularse usando la función <a href="/es/dax/function/datesbetween">DATESBETWEEN</a> que devuelve el conjunto de fechas entre dos dadas. Si el calendario está contenido en la tabla Calendar, tendríamos, por lo tanto, que codificar la siguiente medida:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
Primera fecha disponible,
Última fecha del contexto actual
)
)
Ahora bien, es el cálculo de esas dos fechas lo que resulta más complejo, pues queremos que la primera fecha ("<em>Primera fecha disponible</em>") sea absoluta y haga referencia a la primera fecha disponible en el calendario, mientras que la segunda ("<em>Última fecha del contexto actual</em>") queremos que se adapte al contexto.
Para la obtención de la primera fecha disponible en el calendario deberemos asegurarnos de que no se están aplicando filtros al mismo, para lo que podemos usar la función <a href="/es/dax/function/all">ALL</a> (lo que va a devolver una tabla). Y para la extracción de la primera fecha disponible de dicha tabla no podemos usar la función <a href="/es/dax/function/min">MIN</a> pues ésta exige una columna como argumento, de forma que tendremos que usar la función <a href="/es/dax/function/firstdate">FIRSTDATE</a>, que sí acepta una tabla como argumento y devuelve otra tabla (con la fecha más antigua disponible), tabla que podemos pasar a la función <a href="/es/dax/function/calculate">CALCULATE</a> como argumento de filtro:
FIRSTDATE(ALL(Sales[Order Date]))
Para el cálculo de la última fecha del contexto actual no tenemos más que utilizar la función <a href="/es/dax/function/max">MAX</a> pasando como argumento la columna temporal que está desagregando nuestro objeto visual: la columna 'Calendar'[Date]. Es decir, la última fecha del contexto actual vendría dada por:
MAX('Calendar'[Date])
Es decir, la expresión
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
...va a devolver el conjunto de fechas del calendario entre la más antigua disponible y la última implicada en el contexto actual. Podemos escribir, por lo tanto, la medida que devuelve las ventas acumuladas:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
)
Si quisiéramos utilizar variables para hacer más legible el código, podríamos crear dos variables, __firstdate y __lastDate conteniendo las dos fechas implicadas en el código anterior:
Accumulated sales =
VAR __firstDate = FIRSTDATE(ALL(Sales[Order Date]))
VAR __lastDate = MAX('Calendar'[Date])
RETURN
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
__firstDate,
__lastDate
)
)
Ahora, si llevamos la medida anterior a nuestra matriz, comprobamos que se están acumulando las ventas tal y como queríamos:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_02.png"></a>
Y, por supuesto, si mostramos la matriz desagregada por cualquier otro nivel de nuestra jerarquía temporal, por trimestres, por ejemplo, el cálculo de las ventas acumuladas sigue realizándose correctamente:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_03.png"></a>', 'es') (Line: 118)
Drupal\filter\Element\ProcessedText::preRenderText(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 88)
__TwigTemplate_a7d6005c89ae729617b9a0c2bccb1776->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 46)
__TwigTemplate_804f7948456cfe20e11a34c43439c7c2->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 43)
__TwigTemplate_bd990293b89f3b78c69fe0ee2f7828b5->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/contrib/classy/templates/field/field--text-with-summary.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('field', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 446)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 74)
__TwigTemplate_94047fbdba6937b76a4479dfa1763452->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/custom/yg_aesthetic/templates/node.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('node', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 242)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 235)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.view') (Line: 174)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\mysql\Driver\Database\mysql\Select::$alterTags is deprecated in Drupal\Core\Database\Query\Select->addTag() (line 149 of core/lib/Drupal/Core/Database/Query/Select.php).
Drupal\Core\Database\Query\Select->addTag('entity_query') (Line: 147)
Drupal\Core\Entity\Query\Sql\Query->prepare() (Line: 80)
Drupal\Core\Entity\Query\Sql\Query->execute() (Line: 640)
Drupal\Core\Entity\EntityStorageBase->loadByProperties(Array) (Line: 63)
Drupal\Core\Entity\EntityRepository->loadEntityByUuid('file', 'insert-max_800_px-dab86cbb-c629-45d8-9afa-ee730c81aa40') (Line: 124)
Drupal\editor\Plugin\Filter\EditorFileReference->process('Un escenario frecuente es aquel en el que queremos calcular el total acumulado, incluyendo todos los datos hasta una cierta fecha y no solo los implicados en el contexto de filtro actual. Por ejemplo, si suponemos la existencia de una tabla de ventas Sales que contiene una columna Amount con la cifra de ventas, podríamos definir una medida que calculase la suma de esta columna con la siguiente expresión DAX:
Sales = SUM(Sales[Amount])
Lógicamente, esta medida se va a adaptar al contexto de filtro, por lo que si la llevamos a una matriz en la que se esté desagregando las ventas por año:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_01.png"></a>
...vemos que, para cada año, la cifra de ventas mostrada incluye solo las ventas de dicho año.
Lo que querríamos sería que, en cada evaluación de la medida, el período temporal considerado comenzase el primer día para que el hubo ventas (supongamos que el 1 de enero de 2015) y se extendiese hasta la última fecha del "período actual". Por ejemplo, en la cifra correspondiente al año 2018 el período actual es el correspondiente a los 365 días de dicho año. Pues bien, para el cálculo del acumulado para dicho año querríamos que se considerase el período comprendido entre el 1 de enero de 2015 y el 31 de diciembre de 2018. Es decir, escrito en pseudo-código:
Accumulated sales =
CALCULATE(
[Sales],
Período entre la primera fecha disponible y la última fecha del contexto actual
)
El período en cuestión puede calcularse usando la función <a href="/es/dax/function/datesbetween">DATESBETWEEN</a> que devuelve el conjunto de fechas entre dos dadas. Si el calendario está contenido en la tabla Calendar, tendríamos, por lo tanto, que codificar la siguiente medida:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
Primera fecha disponible,
Última fecha del contexto actual
)
)
Ahora bien, es el cálculo de esas dos fechas lo que resulta más complejo, pues queremos que la primera fecha ("<em>Primera fecha disponible</em>") sea absoluta y haga referencia a la primera fecha disponible en el calendario, mientras que la segunda ("<em>Última fecha del contexto actual</em>") queremos que se adapte al contexto.
Para la obtención de la primera fecha disponible en el calendario deberemos asegurarnos de que no se están aplicando filtros al mismo, para lo que podemos usar la función <a href="/es/dax/function/all">ALL</a> (lo que va a devolver una tabla). Y para la extracción de la primera fecha disponible de dicha tabla no podemos usar la función <a href="/es/dax/function/min">MIN</a> pues ésta exige una columna como argumento, de forma que tendremos que usar la función <a href="/es/dax/function/firstdate">FIRSTDATE</a>, que sí acepta una tabla como argumento y devuelve otra tabla (con la fecha más antigua disponible), tabla que podemos pasar a la función <a href="/es/dax/function/calculate">CALCULATE</a> como argumento de filtro:
FIRSTDATE(ALL(Sales[Order Date]))
Para el cálculo de la última fecha del contexto actual no tenemos más que utilizar la función <a href="/es/dax/function/max">MAX</a> pasando como argumento la columna temporal que está desagregando nuestro objeto visual: la columna 'Calendar'[Date]. Es decir, la última fecha del contexto actual vendría dada por:
MAX('Calendar'[Date])
Es decir, la expresión
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
...va a devolver el conjunto de fechas del calendario entre la más antigua disponible y la última implicada en el contexto actual. Podemos escribir, por lo tanto, la medida que devuelve las ventas acumuladas:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
)
Si quisiéramos utilizar variables para hacer más legible el código, podríamos crear dos variables, __firstdate y __lastDate conteniendo las dos fechas implicadas en el código anterior:
Accumulated sales =
VAR __firstDate = FIRSTDATE(ALL(Sales[Order Date]))
VAR __lastDate = MAX('Calendar'[Date])
RETURN
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
__firstDate,
__lastDate
)
)
Ahora, si llevamos la medida anterior a nuestra matriz, comprobamos que se están acumulando las ventas tal y como queríamos:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_02.png"></a>
Y, por supuesto, si mostramos la matriz desagregada por cualquier otro nivel de nuestra jerarquía temporal, por trimestres, por ejemplo, el cálculo de las ventas acumuladas sigue realizándose correctamente:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_03.png"></a>', 'es') (Line: 118)
Drupal\filter\Element\ProcessedText::preRenderText(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 88)
__TwigTemplate_a7d6005c89ae729617b9a0c2bccb1776->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 46)
__TwigTemplate_804f7948456cfe20e11a34c43439c7c2->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 43)
__TwigTemplate_bd990293b89f3b78c69fe0ee2f7828b5->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/contrib/classy/templates/field/field--text-with-summary.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('field', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 446)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 74)
__TwigTemplate_94047fbdba6937b76a4479dfa1763452->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/custom/yg_aesthetic/templates/node.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('node', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 242)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 235)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.view') (Line: 174)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\mysql\Driver\Database\mysql\Select::$alterMetaData is deprecated in Drupal\Core\Database\Query\Select->addMetaData() (line 178 of core/lib/Drupal/Core/Database/Query/Select.php).
Drupal\Core\Database\Query\Select->addMetaData('entity_type', 'file') (Line: 115)
Drupal\Core\Entity\Query\Sql\Query->prepare() (Line: 80)
Drupal\Core\Entity\Query\Sql\Query->execute() (Line: 640)
Drupal\Core\Entity\EntityStorageBase->loadByProperties(Array) (Line: 63)
Drupal\Core\Entity\EntityRepository->loadEntityByUuid('file', 'insert-max_800_px-e40ca511-b94c-46b4-bc19-759574e3d53f') (Line: 95)
Drupal\editor\Plugin\Filter\EditorFileReference->process('Un escenario frecuente es aquel en el que queremos calcular el total acumulado, incluyendo todos los datos hasta una cierta fecha y no solo los implicados en el contexto de filtro actual. Por ejemplo, si suponemos la existencia de una tabla de ventas Sales que contiene una columna Amount con la cifra de ventas, podríamos definir una medida que calculase la suma de esta columna con la siguiente expresión DAX:
Sales = SUM(Sales[Amount])
Lógicamente, esta medida se va a adaptar al contexto de filtro, por lo que si la llevamos a una matriz en la que se esté desagregando las ventas por año:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_01.png"></a>
...vemos que, para cada año, la cifra de ventas mostrada incluye solo las ventas de dicho año.
Lo que querríamos sería que, en cada evaluación de la medida, el período temporal considerado comenzase el primer día para que el hubo ventas (supongamos que el 1 de enero de 2015) y se extendiese hasta la última fecha del "período actual". Por ejemplo, en la cifra correspondiente al año 2018 el período actual es el correspondiente a los 365 días de dicho año. Pues bien, para el cálculo del acumulado para dicho año querríamos que se considerase el período comprendido entre el 1 de enero de 2015 y el 31 de diciembre de 2018. Es decir, escrito en pseudo-código:
Accumulated sales =
CALCULATE(
[Sales],
Período entre la primera fecha disponible y la última fecha del contexto actual
)
El período en cuestión puede calcularse usando la función <a href="/es/dax/function/datesbetween">DATESBETWEEN</a> que devuelve el conjunto de fechas entre dos dadas. Si el calendario está contenido en la tabla Calendar, tendríamos, por lo tanto, que codificar la siguiente medida:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
Primera fecha disponible,
Última fecha del contexto actual
)
)
Ahora bien, es el cálculo de esas dos fechas lo que resulta más complejo, pues queremos que la primera fecha ("<em>Primera fecha disponible</em>") sea absoluta y haga referencia a la primera fecha disponible en el calendario, mientras que la segunda ("<em>Última fecha del contexto actual</em>") queremos que se adapte al contexto.
Para la obtención de la primera fecha disponible en el calendario deberemos asegurarnos de que no se están aplicando filtros al mismo, para lo que podemos usar la función <a href="/es/dax/function/all">ALL</a> (lo que va a devolver una tabla). Y para la extracción de la primera fecha disponible de dicha tabla no podemos usar la función <a href="/es/dax/function/min">MIN</a> pues ésta exige una columna como argumento, de forma que tendremos que usar la función <a href="/es/dax/function/firstdate">FIRSTDATE</a>, que sí acepta una tabla como argumento y devuelve otra tabla (con la fecha más antigua disponible), tabla que podemos pasar a la función <a href="/es/dax/function/calculate">CALCULATE</a> como argumento de filtro:
FIRSTDATE(ALL(Sales[Order Date]))
Para el cálculo de la última fecha del contexto actual no tenemos más que utilizar la función <a href="/es/dax/function/max">MAX</a> pasando como argumento la columna temporal que está desagregando nuestro objeto visual: la columna 'Calendar'[Date]. Es decir, la última fecha del contexto actual vendría dada por:
MAX('Calendar'[Date])
Es decir, la expresión
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
...va a devolver el conjunto de fechas del calendario entre la más antigua disponible y la última implicada en el contexto actual. Podemos escribir, por lo tanto, la medida que devuelve las ventas acumuladas:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
)
Si quisiéramos utilizar variables para hacer más legible el código, podríamos crear dos variables, __firstdate y __lastDate conteniendo las dos fechas implicadas en el código anterior:
Accumulated sales =
VAR __firstDate = FIRSTDATE(ALL(Sales[Order Date]))
VAR __lastDate = MAX('Calendar'[Date])
RETURN
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
__firstDate,
__lastDate
)
)
Ahora, si llevamos la medida anterior a nuestra matriz, comprobamos que se están acumulando las ventas tal y como queríamos:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_02.png"></a>
Y, por supuesto, si mostramos la matriz desagregada por cualquier otro nivel de nuestra jerarquía temporal, por trimestres, por ejemplo, el cálculo de las ventas acumuladas sigue realizándose correctamente:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_03.png"></a>', 'es') (Line: 118)
Drupal\filter\Element\ProcessedText::preRenderText(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 88)
__TwigTemplate_a7d6005c89ae729617b9a0c2bccb1776->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 46)
__TwigTemplate_804f7948456cfe20e11a34c43439c7c2->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 43)
__TwigTemplate_bd990293b89f3b78c69fe0ee2f7828b5->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/contrib/classy/templates/field/field--text-with-summary.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('field', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 446)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 74)
__TwigTemplate_94047fbdba6937b76a4479dfa1763452->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/custom/yg_aesthetic/templates/node.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('node', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 242)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 235)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.view') (Line: 174)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\mysql\Driver\Database\mysql\Select::$alterTags is deprecated in Drupal\Core\Database\Query\Select->addTag() (line 149 of core/lib/Drupal/Core/Database/Query/Select.php).
Drupal\Core\Database\Query\Select->addTag('entity_query') (Line: 147)
Drupal\Core\Entity\Query\Sql\Query->prepare() (Line: 80)
Drupal\Core\Entity\Query\Sql\Query->execute() (Line: 640)
Drupal\Core\Entity\EntityStorageBase->loadByProperties(Array) (Line: 63)
Drupal\Core\Entity\EntityRepository->loadEntityByUuid('file', 'insert-max_800_px-e40ca511-b94c-46b4-bc19-759574e3d53f') (Line: 95)
Drupal\editor\Plugin\Filter\EditorFileReference->process('Un escenario frecuente es aquel en el que queremos calcular el total acumulado, incluyendo todos los datos hasta una cierta fecha y no solo los implicados en el contexto de filtro actual. Por ejemplo, si suponemos la existencia de una tabla de ventas Sales que contiene una columna Amount con la cifra de ventas, podríamos definir una medida que calculase la suma de esta columna con la siguiente expresión DAX:
Sales = SUM(Sales[Amount])
Lógicamente, esta medida se va a adaptar al contexto de filtro, por lo que si la llevamos a una matriz en la que se esté desagregando las ventas por año:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_01.png"></a>
...vemos que, para cada año, la cifra de ventas mostrada incluye solo las ventas de dicho año.
Lo que querríamos sería que, en cada evaluación de la medida, el período temporal considerado comenzase el primer día para que el hubo ventas (supongamos que el 1 de enero de 2015) y se extendiese hasta la última fecha del "período actual". Por ejemplo, en la cifra correspondiente al año 2018 el período actual es el correspondiente a los 365 días de dicho año. Pues bien, para el cálculo del acumulado para dicho año querríamos que se considerase el período comprendido entre el 1 de enero de 2015 y el 31 de diciembre de 2018. Es decir, escrito en pseudo-código:
Accumulated sales =
CALCULATE(
[Sales],
Período entre la primera fecha disponible y la última fecha del contexto actual
)
El período en cuestión puede calcularse usando la función <a href="/es/dax/function/datesbetween">DATESBETWEEN</a> que devuelve el conjunto de fechas entre dos dadas. Si el calendario está contenido en la tabla Calendar, tendríamos, por lo tanto, que codificar la siguiente medida:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
Primera fecha disponible,
Última fecha del contexto actual
)
)
Ahora bien, es el cálculo de esas dos fechas lo que resulta más complejo, pues queremos que la primera fecha ("<em>Primera fecha disponible</em>") sea absoluta y haga referencia a la primera fecha disponible en el calendario, mientras que la segunda ("<em>Última fecha del contexto actual</em>") queremos que se adapte al contexto.
Para la obtención de la primera fecha disponible en el calendario deberemos asegurarnos de que no se están aplicando filtros al mismo, para lo que podemos usar la función <a href="/es/dax/function/all">ALL</a> (lo que va a devolver una tabla). Y para la extracción de la primera fecha disponible de dicha tabla no podemos usar la función <a href="/es/dax/function/min">MIN</a> pues ésta exige una columna como argumento, de forma que tendremos que usar la función <a href="/es/dax/function/firstdate">FIRSTDATE</a>, que sí acepta una tabla como argumento y devuelve otra tabla (con la fecha más antigua disponible), tabla que podemos pasar a la función <a href="/es/dax/function/calculate">CALCULATE</a> como argumento de filtro:
FIRSTDATE(ALL(Sales[Order Date]))
Para el cálculo de la última fecha del contexto actual no tenemos más que utilizar la función <a href="/es/dax/function/max">MAX</a> pasando como argumento la columna temporal que está desagregando nuestro objeto visual: la columna 'Calendar'[Date]. Es decir, la última fecha del contexto actual vendría dada por:
MAX('Calendar'[Date])
Es decir, la expresión
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
...va a devolver el conjunto de fechas del calendario entre la más antigua disponible y la última implicada en el contexto actual. Podemos escribir, por lo tanto, la medida que devuelve las ventas acumuladas:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
)
Si quisiéramos utilizar variables para hacer más legible el código, podríamos crear dos variables, __firstdate y __lastDate conteniendo las dos fechas implicadas en el código anterior:
Accumulated sales =
VAR __firstDate = FIRSTDATE(ALL(Sales[Order Date]))
VAR __lastDate = MAX('Calendar'[Date])
RETURN
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
__firstDate,
__lastDate
)
)
Ahora, si llevamos la medida anterior a nuestra matriz, comprobamos que se están acumulando las ventas tal y como queríamos:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_02.png"></a>
Y, por supuesto, si mostramos la matriz desagregada por cualquier otro nivel de nuestra jerarquía temporal, por trimestres, por ejemplo, el cálculo de las ventas acumuladas sigue realizándose correctamente:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_03.png"></a>', 'es') (Line: 118)
Drupal\filter\Element\ProcessedText::preRenderText(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 88)
__TwigTemplate_a7d6005c89ae729617b9a0c2bccb1776->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 46)
__TwigTemplate_804f7948456cfe20e11a34c43439c7c2->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 43)
__TwigTemplate_bd990293b89f3b78c69fe0ee2f7828b5->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/contrib/classy/templates/field/field--text-with-summary.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('field', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 446)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 74)
__TwigTemplate_94047fbdba6937b76a4479dfa1763452->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/custom/yg_aesthetic/templates/node.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('node', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 242)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 235)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.view') (Line: 174)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\mysql\Driver\Database\mysql\Select::$alterMetaData is deprecated in Drupal\Core\Database\Query\Select->addMetaData() (line 178 of core/lib/Drupal/Core/Database/Query/Select.php).
Drupal\Core\Database\Query\Select->addMetaData('entity_type', 'file') (Line: 115)
Drupal\Core\Entity\Query\Sql\Query->prepare() (Line: 80)
Drupal\Core\Entity\Query\Sql\Query->execute() (Line: 640)
Drupal\Core\Entity\EntityStorageBase->loadByProperties(Array) (Line: 63)
Drupal\Core\Entity\EntityRepository->loadEntityByUuid('file', 'insert-max_800_px-e40ca511-b94c-46b4-bc19-759574e3d53f') (Line: 124)
Drupal\editor\Plugin\Filter\EditorFileReference->process('Un escenario frecuente es aquel en el que queremos calcular el total acumulado, incluyendo todos los datos hasta una cierta fecha y no solo los implicados en el contexto de filtro actual. Por ejemplo, si suponemos la existencia de una tabla de ventas Sales que contiene una columna Amount con la cifra de ventas, podríamos definir una medida que calculase la suma de esta columna con la siguiente expresión DAX:
Sales = SUM(Sales[Amount])
Lógicamente, esta medida se va a adaptar al contexto de filtro, por lo que si la llevamos a una matriz en la que se esté desagregando las ventas por año:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_01.png"></a>
...vemos que, para cada año, la cifra de ventas mostrada incluye solo las ventas de dicho año.
Lo que querríamos sería que, en cada evaluación de la medida, el período temporal considerado comenzase el primer día para que el hubo ventas (supongamos que el 1 de enero de 2015) y se extendiese hasta la última fecha del "período actual". Por ejemplo, en la cifra correspondiente al año 2018 el período actual es el correspondiente a los 365 días de dicho año. Pues bien, para el cálculo del acumulado para dicho año querríamos que se considerase el período comprendido entre el 1 de enero de 2015 y el 31 de diciembre de 2018. Es decir, escrito en pseudo-código:
Accumulated sales =
CALCULATE(
[Sales],
Período entre la primera fecha disponible y la última fecha del contexto actual
)
El período en cuestión puede calcularse usando la función <a href="/es/dax/function/datesbetween">DATESBETWEEN</a> que devuelve el conjunto de fechas entre dos dadas. Si el calendario está contenido en la tabla Calendar, tendríamos, por lo tanto, que codificar la siguiente medida:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
Primera fecha disponible,
Última fecha del contexto actual
)
)
Ahora bien, es el cálculo de esas dos fechas lo que resulta más complejo, pues queremos que la primera fecha ("<em>Primera fecha disponible</em>") sea absoluta y haga referencia a la primera fecha disponible en el calendario, mientras que la segunda ("<em>Última fecha del contexto actual</em>") queremos que se adapte al contexto.
Para la obtención de la primera fecha disponible en el calendario deberemos asegurarnos de que no se están aplicando filtros al mismo, para lo que podemos usar la función <a href="/es/dax/function/all">ALL</a> (lo que va a devolver una tabla). Y para la extracción de la primera fecha disponible de dicha tabla no podemos usar la función <a href="/es/dax/function/min">MIN</a> pues ésta exige una columna como argumento, de forma que tendremos que usar la función <a href="/es/dax/function/firstdate">FIRSTDATE</a>, que sí acepta una tabla como argumento y devuelve otra tabla (con la fecha más antigua disponible), tabla que podemos pasar a la función <a href="/es/dax/function/calculate">CALCULATE</a> como argumento de filtro:
FIRSTDATE(ALL(Sales[Order Date]))
Para el cálculo de la última fecha del contexto actual no tenemos más que utilizar la función <a href="/es/dax/function/max">MAX</a> pasando como argumento la columna temporal que está desagregando nuestro objeto visual: la columna 'Calendar'[Date]. Es decir, la última fecha del contexto actual vendría dada por:
MAX('Calendar'[Date])
Es decir, la expresión
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
...va a devolver el conjunto de fechas del calendario entre la más antigua disponible y la última implicada en el contexto actual. Podemos escribir, por lo tanto, la medida que devuelve las ventas acumuladas:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
)
Si quisiéramos utilizar variables para hacer más legible el código, podríamos crear dos variables, __firstdate y __lastDate conteniendo las dos fechas implicadas en el código anterior:
Accumulated sales =
VAR __firstDate = FIRSTDATE(ALL(Sales[Order Date]))
VAR __lastDate = MAX('Calendar'[Date])
RETURN
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
__firstDate,
__lastDate
)
)
Ahora, si llevamos la medida anterior a nuestra matriz, comprobamos que se están acumulando las ventas tal y como queríamos:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_02.png"></a>
Y, por supuesto, si mostramos la matriz desagregada por cualquier otro nivel de nuestra jerarquía temporal, por trimestres, por ejemplo, el cálculo de las ventas acumuladas sigue realizándose correctamente:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_03.png"></a>', 'es') (Line: 118)
Drupal\filter\Element\ProcessedText::preRenderText(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 88)
__TwigTemplate_a7d6005c89ae729617b9a0c2bccb1776->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 46)
__TwigTemplate_804f7948456cfe20e11a34c43439c7c2->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 43)
__TwigTemplate_bd990293b89f3b78c69fe0ee2f7828b5->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/contrib/classy/templates/field/field--text-with-summary.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('field', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 446)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 74)
__TwigTemplate_94047fbdba6937b76a4479dfa1763452->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/custom/yg_aesthetic/templates/node.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('node', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 242)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 235)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.view') (Line: 174)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\mysql\Driver\Database\mysql\Select::$alterTags is deprecated in Drupal\Core\Database\Query\Select->addTag() (line 149 of core/lib/Drupal/Core/Database/Query/Select.php).
Drupal\Core\Database\Query\Select->addTag('entity_query') (Line: 147)
Drupal\Core\Entity\Query\Sql\Query->prepare() (Line: 80)
Drupal\Core\Entity\Query\Sql\Query->execute() (Line: 640)
Drupal\Core\Entity\EntityStorageBase->loadByProperties(Array) (Line: 63)
Drupal\Core\Entity\EntityRepository->loadEntityByUuid('file', 'insert-max_800_px-e40ca511-b94c-46b4-bc19-759574e3d53f') (Line: 124)
Drupal\editor\Plugin\Filter\EditorFileReference->process('Un escenario frecuente es aquel en el que queremos calcular el total acumulado, incluyendo todos los datos hasta una cierta fecha y no solo los implicados en el contexto de filtro actual. Por ejemplo, si suponemos la existencia de una tabla de ventas Sales que contiene una columna Amount con la cifra de ventas, podríamos definir una medida que calculase la suma de esta columna con la siguiente expresión DAX:
Sales = SUM(Sales[Amount])
Lógicamente, esta medida se va a adaptar al contexto de filtro, por lo que si la llevamos a una matriz en la que se esté desagregando las ventas por año:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_01.png"></a>
...vemos que, para cada año, la cifra de ventas mostrada incluye solo las ventas de dicho año.
Lo que querríamos sería que, en cada evaluación de la medida, el período temporal considerado comenzase el primer día para que el hubo ventas (supongamos que el 1 de enero de 2015) y se extendiese hasta la última fecha del "período actual". Por ejemplo, en la cifra correspondiente al año 2018 el período actual es el correspondiente a los 365 días de dicho año. Pues bien, para el cálculo del acumulado para dicho año querríamos que se considerase el período comprendido entre el 1 de enero de 2015 y el 31 de diciembre de 2018. Es decir, escrito en pseudo-código:
Accumulated sales =
CALCULATE(
[Sales],
Período entre la primera fecha disponible y la última fecha del contexto actual
)
El período en cuestión puede calcularse usando la función <a href="/es/dax/function/datesbetween">DATESBETWEEN</a> que devuelve el conjunto de fechas entre dos dadas. Si el calendario está contenido en la tabla Calendar, tendríamos, por lo tanto, que codificar la siguiente medida:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
Primera fecha disponible,
Última fecha del contexto actual
)
)
Ahora bien, es el cálculo de esas dos fechas lo que resulta más complejo, pues queremos que la primera fecha ("<em>Primera fecha disponible</em>") sea absoluta y haga referencia a la primera fecha disponible en el calendario, mientras que la segunda ("<em>Última fecha del contexto actual</em>") queremos que se adapte al contexto.
Para la obtención de la primera fecha disponible en el calendario deberemos asegurarnos de que no se están aplicando filtros al mismo, para lo que podemos usar la función <a href="/es/dax/function/all">ALL</a> (lo que va a devolver una tabla). Y para la extracción de la primera fecha disponible de dicha tabla no podemos usar la función <a href="/es/dax/function/min">MIN</a> pues ésta exige una columna como argumento, de forma que tendremos que usar la función <a href="/es/dax/function/firstdate">FIRSTDATE</a>, que sí acepta una tabla como argumento y devuelve otra tabla (con la fecha más antigua disponible), tabla que podemos pasar a la función <a href="/es/dax/function/calculate">CALCULATE</a> como argumento de filtro:
FIRSTDATE(ALL(Sales[Order Date]))
Para el cálculo de la última fecha del contexto actual no tenemos más que utilizar la función <a href="/es/dax/function/max">MAX</a> pasando como argumento la columna temporal que está desagregando nuestro objeto visual: la columna 'Calendar'[Date]. Es decir, la última fecha del contexto actual vendría dada por:
MAX('Calendar'[Date])
Es decir, la expresión
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
...va a devolver el conjunto de fechas del calendario entre la más antigua disponible y la última implicada en el contexto actual. Podemos escribir, por lo tanto, la medida que devuelve las ventas acumuladas:
Accumulated sales =
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
FIRSTDATE(ALL(Sales[Order Date])),
MAX('Calendar'[Date])
)
)
Si quisiéramos utilizar variables para hacer más legible el código, podríamos crear dos variables, __firstdate y __lastDate conteniendo las dos fechas implicadas en el código anterior:
Accumulated sales =
VAR __firstDate = FIRSTDATE(ALL(Sales[Order Date]))
VAR __lastDate = MAX('Calendar'[Date])
RETURN
CALCULATE(
[Sales],
DATESBETWEEN(
'Calendar'[Date],
__firstDate,
__lastDate
)
)
Ahora, si llevamos la medida anterior a nuestra matriz, comprobamos que se están acumulando las ventas tal y como queríamos:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_02.png"></a>
Y, por supuesto, si mostramos la matriz desagregada por cualquier otro nivel de nuestra jerarquía temporal, por trimestres, por ejemplo, el cálculo de las ventas acumuladas sigue realizándose correctamente:
<a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_03.png"></a>', 'es') (Line: 118)
Drupal\filter\Element\ProcessedText::preRenderText(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 88)
__TwigTemplate_a7d6005c89ae729617b9a0c2bccb1776->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 46)
__TwigTemplate_804f7948456cfe20e11a34c43439c7c2->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 43)
__TwigTemplate_bd990293b89f3b78c69fe0ee2f7828b5->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/contrib/classy/templates/field/field--text-with-summary.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('field', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 446)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 74)
__TwigTemplate_94047fbdba6937b76a4479dfa1763452->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('themes/custom/yg_aesthetic/templates/node.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('node', Array) (Line: 433)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 242)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 235)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.view') (Line: 174)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Return type of Drupal\google_analytics\Component\Render\GoogleAnalyticsJavaScriptSnippet::jsonSerialize() should either be compatible with JsonSerializable::jsonSerialize(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in include() (line 10 of modules/contrib/google_analytics/src/Component/Render/GoogleAnalyticsJavaScriptSnippet.php).
include('/var/www/vhosts/interactivechaos.ovh/httpdocs/modules/contrib/google_analytics/src/Component/Render/GoogleAnalyticsJavaScriptSnippet.php') (Line: 578)
Composer\Autoload\ClassLoader::Composer\Autoload\{closure}('/var/www/vhosts/interactivechaos.ovh/httpdocs/modules/contrib/google_analytics/src/Component/Render/GoogleAnalyticsJavaScriptSnippet.php') (Line: 432)
Composer\Autoload\ClassLoader->loadClass('Drupal\google_analytics\Component\Render\GoogleAnalyticsJavaScriptSnippet') (Line: 372)
google_analytics_page_attachments(Array) (Line: 313)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}(Object, 'google_analytics') (Line: 405)
Drupal\Core\Extension\ModuleHandler->invokeAllWith('page_attachments', Object) (Line: 310)
Drupal\Core\Render\MainContent\HtmlRenderer->invokePageAttachmentHooks(Array) (Line: 288)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.view') (Line: 174)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Use of "static" in callables is deprecated in Drupal\user\Entity\Role::postLoad() (line 172 of core/modules/user/src/Entity/Role.php).
Drupal\user\Entity\Role::postLoad(Object, Array) (Line: 423)
Drupal\Core\Entity\EntityStorageBase->postLoad(Array) (Line: 353)
Drupal\Core\Entity\EntityStorageBase->loadMultiple() (Line: 126)
eu_cookie_compliance_page_attachments(Array) (Line: 313)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}(Object, 'eu_cookie_compliance') (Line: 405)
Drupal\Core\Extension\ModuleHandler->invokeAllWith('page_attachments', Object) (Line: 310)
Drupal\Core\Render\MainContent\HtmlRenderer->invokePageAttachmentHooks(Array) (Line: 288)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.view') (Line: 174)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\views\ManyToOneHelper::$handler is deprecated in Drupal\views\ManyToOneHelper->__construct() (line 24 of core/modules/views/src/ManyToOneHelper.php).
Drupal\views\ManyToOneHelper->__construct(Object) (Line: 51)
Drupal\views\Plugin\views\filter\ManyToOne->defineOptions() (Line: 117)
Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid->defineOptions() (Line: 141)
Drupal\views\Plugin\views\PluginBase->init(Object, Object, Array) (Line: 104)
Drupal\views\Plugin\views\HandlerBase->init(Object, Object, Array) (Line: 95)
Drupal\views\Plugin\views\filter\FilterPluginBase->init(Object, Object, Array) (Line: 44)
Drupal\views\Plugin\views\filter\InOperator->init(Object, Object, Array) (Line: 36)
Drupal\views\Plugin\views\filter\ManyToOne->init(Object, Object, Array) (Line: 98)
Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid->init(Object, Object, Array) (Line: 894)
Drupal\views\Plugin\views\display\DisplayPluginBase->getHandlers('filter') (Line: 1045)
Drupal\views\ViewExecutable->_initHandler('filter', Array) (Line: 903)
Drupal\views\ViewExecutable->initHandlers() (Line: 2633)
Drupal\views\Plugin\views\display\DisplayPluginBase->viewExposedFormBlocks() (Line: 35)
Drupal\views\Plugin\Block\ViewsExposedFilterBlock->build() (Line: 171)
Drupal\block\BlockViewBuilder::preRender(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, 1) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, 1) (Line: 160)
Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 159)
Drupal\Core\Render\Renderer->renderPlain(Array) (Line: 175)
Drupal\Core\Render\Renderer->renderPlaceholder('', Array) (Line: 665)
Drupal\Core\Render\Renderer->replacePlaceholders(Array) (Line: 550)
Drupal\Core\Render\Renderer->doRender(Array, 1) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, 1) (Line: 148)
Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 147)
Drupal\Core\Render\Renderer->renderRoot(Array) (Line: 279)
Drupal\Core\Render\HtmlResponseAttachmentsProcessor->renderPlaceholders(Object) (Line: 71)
Drupal\big_pipe\Render\BigPipeResponseAttachmentsProcessor->processAttachments(Object) (Line: 45)
Drupal\Core\EventSubscriber\HtmlResponseSubscriber->onRespond(Object, 'kernel.response', Object)
call_user_func(Array, Object, 'kernel.response', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.response') (Line: 202)
Symfony\Component\HttpKernel\HttpKernel->filterResponse(Object, Object, 1) (Line: 190)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\views\ManyToOneHelper::$handler is deprecated in Drupal\views\ManyToOneHelper->__construct() (line 24 of core/modules/views/src/ManyToOneHelper.php).
Drupal\views\ManyToOneHelper->__construct(Object) (Line: 51)
Drupal\views\Plugin\views\filter\ManyToOne->defineOptions() (Line: 117)
Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid->defineOptions() (Line: 228)
Drupal\views\Plugin\views\PluginBase->unpackOptions(Array, Array) (Line: 144)
Drupal\views\Plugin\views\PluginBase->init(Object, Object, Array) (Line: 104)
Drupal\views\Plugin\views\HandlerBase->init(Object, Object, Array) (Line: 95)
Drupal\views\Plugin\views\filter\FilterPluginBase->init(Object, Object, Array) (Line: 44)
Drupal\views\Plugin\views\filter\InOperator->init(Object, Object, Array) (Line: 36)
Drupal\views\Plugin\views\filter\ManyToOne->init(Object, Object, Array) (Line: 98)
Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid->init(Object, Object, Array) (Line: 894)
Drupal\views\Plugin\views\display\DisplayPluginBase->getHandlers('filter') (Line: 1045)
Drupal\views\ViewExecutable->_initHandler('filter', Array) (Line: 903)
Drupal\views\ViewExecutable->initHandlers() (Line: 2633)
Drupal\views\Plugin\views\display\DisplayPluginBase->viewExposedFormBlocks() (Line: 35)
Drupal\views\Plugin\Block\ViewsExposedFilterBlock->build() (Line: 171)
Drupal\block\BlockViewBuilder::preRender(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, 1) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, 1) (Line: 160)
Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 159)
Drupal\Core\Render\Renderer->renderPlain(Array) (Line: 175)
Drupal\Core\Render\Renderer->renderPlaceholder('', Array) (Line: 665)
Drupal\Core\Render\Renderer->replacePlaceholders(Array) (Line: 550)
Drupal\Core\Render\Renderer->doRender(Array, 1) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, 1) (Line: 148)
Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 147)
Drupal\Core\Render\Renderer->renderRoot(Array) (Line: 279)
Drupal\Core\Render\HtmlResponseAttachmentsProcessor->renderPlaceholders(Object) (Line: 71)
Drupal\big_pipe\Render\BigPipeResponseAttachmentsProcessor->processAttachments(Object) (Line: 45)
Drupal\Core\EventSubscriber\HtmlResponseSubscriber->onRespond(Object, 'kernel.response', Object)
call_user_func(Array, Object, 'kernel.response', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.response') (Line: 202)
Symfony\Component\HttpKernel\HttpKernel->filterResponse(Object, Object, 1) (Line: 190)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\views\ManyToOneHelper::$handler is deprecated in Drupal\views\ManyToOneHelper->__construct() (line 24 of core/modules/views/src/ManyToOneHelper.php).
Drupal\views\ManyToOneHelper->__construct(Object) (Line: 51)
Drupal\views\Plugin\views\filter\ManyToOne->defineOptions() (Line: 117)
Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid->defineOptions() (Line: 228)
Drupal\views\Plugin\views\PluginBase->unpackOptions(Array, Array) (Line: 110)
Drupal\views\Plugin\views\HandlerBase->init(Object, Object, Array) (Line: 95)
Drupal\views\Plugin\views\filter\FilterPluginBase->init(Object, Object, Array) (Line: 44)
Drupal\views\Plugin\views\filter\InOperator->init(Object, Object, Array) (Line: 36)
Drupal\views\Plugin\views\filter\ManyToOne->init(Object, Object, Array) (Line: 98)
Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid->init(Object, Object, Array) (Line: 894)
Drupal\views\Plugin\views\display\DisplayPluginBase->getHandlers('filter') (Line: 1045)
Drupal\views\ViewExecutable->_initHandler('filter', Array) (Line: 903)
Drupal\views\ViewExecutable->initHandlers() (Line: 2633)
Drupal\views\Plugin\views\display\DisplayPluginBase->viewExposedFormBlocks() (Line: 35)
Drupal\views\Plugin\Block\ViewsExposedFilterBlock->build() (Line: 171)
Drupal\block\BlockViewBuilder::preRender(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, 1) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, 1) (Line: 160)
Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 159)
Drupal\Core\Render\Renderer->renderPlain(Array) (Line: 175)
Drupal\Core\Render\Renderer->renderPlaceholder('', Array) (Line: 665)
Drupal\Core\Render\Renderer->replacePlaceholders(Array) (Line: 550)
Drupal\Core\Render\Renderer->doRender(Array, 1) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, 1) (Line: 148)
Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 147)
Drupal\Core\Render\Renderer->renderRoot(Array) (Line: 279)
Drupal\Core\Render\HtmlResponseAttachmentsProcessor->renderPlaceholders(Object) (Line: 71)
Drupal\big_pipe\Render\BigPipeResponseAttachmentsProcessor->processAttachments(Object) (Line: 45)
Drupal\Core\EventSubscriber\HtmlResponseSubscriber->onRespond(Object, 'kernel.response', Object)
call_user_func(Array, Object, 'kernel.response', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.response') (Line: 202)
Symfony\Component\HttpKernel\HttpKernel->filterResponse(Object, Object, 1) (Line: 190)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\views\ManyToOneHelper::$handler is deprecated in Drupal\views\ManyToOneHelper->__construct() (line 24 of core/modules/views/src/ManyToOneHelper.php).
Drupal\views\ManyToOneHelper->__construct(Object) (Line: 38)
Drupal\views\Plugin\views\filter\ManyToOne->init(Object, Object, Array) (Line: 98)
Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid->init(Object, Object, Array) (Line: 894)
Drupal\views\Plugin\views\display\DisplayPluginBase->getHandlers('filter') (Line: 1045)
Drupal\views\ViewExecutable->_initHandler('filter', Array) (Line: 903)
Drupal\views\ViewExecutable->initHandlers() (Line: 2633)
Drupal\views\Plugin\views\display\DisplayPluginBase->viewExposedFormBlocks() (Line: 35)
Drupal\views\Plugin\Block\ViewsExposedFilterBlock->build() (Line: 171)
Drupal\block\BlockViewBuilder::preRender(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, 1) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, 1) (Line: 160)
Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 159)
Drupal\Core\Render\Renderer->renderPlain(Array) (Line: 175)
Drupal\Core\Render\Renderer->renderPlaceholder('', Array) (Line: 665)
Drupal\Core\Render\Renderer->replacePlaceholders(Array) (Line: 550)
Drupal\Core\Render\Renderer->doRender(Array, 1) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, 1) (Line: 148)
Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 147)
Drupal\Core\Render\Renderer->renderRoot(Array) (Line: 279)
Drupal\Core\Render\HtmlResponseAttachmentsProcessor->renderPlaceholders(Object) (Line: 71)
Drupal\big_pipe\Render\BigPipeResponseAttachmentsProcessor->processAttachments(Object) (Line: 45)
Drupal\Core\EventSubscriber\HtmlResponseSubscriber->onRespond(Object, 'kernel.response', Object)
call_user_func(Array, Object, 'kernel.response', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.response') (Line: 202)
Symfony\Component\HttpKernel\HttpKernel->filterResponse(Object, Object, 1) (Line: 190)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\mysql\Driver\Database\mysql\Select::$alterMetaData is deprecated in Drupal\Core\Database\Query\Select->addMetaData() (line 178 of core/lib/Drupal/Core/Database/Query/Select.php).
Drupal\Core\Database\Query\Select->addMetaData('entity_type', 'taxonomy_term') (Line: 115)
Drupal\Core\Entity\Query\Sql\Query->prepare() (Line: 80)
Drupal\Core\Entity\Query\Sql\Query->execute() (Line: 228)
Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid->valueForm(Array, Object) (Line: 941)
Drupal\views\Plugin\views\filter\FilterPluginBase->buildExposedForm(Array, Object) (Line: 111)
Drupal\views\Form\ViewsExposedForm->buildForm(Array, Object)
call_user_func_array(Array, Array) (Line: 534)
Drupal\Core\Form\FormBuilder->retrieveForm('views_exposed_form', Object) (Line: 281)
Drupal\Core\Form\FormBuilder->buildForm('\Drupal\views\Form\ViewsExposedForm', Object) (Line: 134)
Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase->renderExposedForm(1) (Line: 2638)
Drupal\views\Plugin\views\display\DisplayPluginBase->viewExposedFormBlocks() (Line: 35)
Drupal\views\Plugin\Block\ViewsExposedFilterBlock->build() (Line: 171)
Drupal\block\BlockViewBuilder::preRender(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, 1) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, 1) (Line: 160)
Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 159)
Drupal\Core\Render\Renderer->renderPlain(Array) (Line: 175)
Drupal\Core\Render\Renderer->renderPlaceholder('', Array) (Line: 665)
Drupal\Core\Render\Renderer->replacePlaceholders(Array) (Line: 550)
Drupal\Core\Render\Renderer->doRender(Array, 1) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, 1) (Line: 148)
Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 147)
Drupal\Core\Render\Renderer->renderRoot(Array) (Line: 279)
Drupal\Core\Render\HtmlResponseAttachmentsProcessor->renderPlaceholders(Object) (Line: 71)
Drupal\big_pipe\Render\BigPipeResponseAttachmentsProcessor->processAttachments(Object) (Line: 45)
Drupal\Core\EventSubscriber\HtmlResponseSubscriber->onRespond(Object, 'kernel.response', Object)
call_user_func(Array, Object, 'kernel.response', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.response') (Line: 202)
Symfony\Component\HttpKernel\HttpKernel->filterResponse(Object, Object, 1) (Line: 190)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
- Deprecated function: Creation of dynamic property Drupal\mysql\Driver\Database\mysql\Select::$alterTags is deprecated in Drupal\Core\Database\Query\Select->addTag() (line 149 of core/lib/Drupal/Core/Database/Query/Select.php).
Drupal\Core\Database\Query\Select->addTag('taxonomy_term_access') (Line: 145)
Drupal\Core\Entity\Query\Sql\Query->prepare() (Line: 80)
Drupal\Core\Entity\Query\Sql\Query->execute() (Line: 228)
Drupal\taxonomy\Plugin\views\filter\TaxonomyIndexTid->valueForm(Array, Object) (Line: 941)
Drupal\views\Plugin\views\filter\FilterPluginBase->buildExposedForm(Array, Object) (Line: 111)
Drupal\views\Form\ViewsExposedForm->buildForm(Array, Object)
call_user_func_array(Array, Array) (Line: 534)
Drupal\Core\Form\FormBuilder->retrieveForm('views_exposed_form', Object) (Line: 281)
Drupal\Core\Form\FormBuilder->buildForm('\Drupal\views\Form\ViewsExposedForm', Object) (Line: 134)
Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase->renderExposedForm(1) (Line: 2638)
Drupal\views\Plugin\views\display\DisplayPluginBase->viewExposedFormBlocks() (Line: 35)
Drupal\views\Plugin\Block\ViewsExposedFilterBlock->build() (Line: 171)
Drupal\block\BlockViewBuilder::preRender(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 788)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 374)
Drupal\Core\Render\Renderer->doRender(Array, 1) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, 1) (Line: 160)
Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 159)
Drupal\Core\Render\Renderer->renderPlain(Array) (Line: 175)
Drupal\Core\Render\Renderer->renderPlaceholder('', Array) (Line: 665)
Drupal\Core\Render\Renderer->replacePlaceholders(Array) (Line: 550)
Drupal\Core\Render\Renderer->doRender(Array, 1) (Line: 204)
Drupal\Core\Render\Renderer->render(Array, 1) (Line: 148)
Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 147)
Drupal\Core\Render\Renderer->renderRoot(Array) (Line: 279)
Drupal\Core\Render\HtmlResponseAttachmentsProcessor->renderPlaceholders(Object) (Line: 71)
Drupal\big_pipe\Render\BigPipeResponseAttachmentsProcessor->processAttachments(Object) (Line: 45)
Drupal\Core\EventSubscriber\HtmlResponseSubscriber->onRespond(Object, 'kernel.response', Object)
call_user_func(Array, Object, 'kernel.response', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.response') (Line: 202)
Symfony\Component\HttpKernel\HttpKernel->filterResponse(Object, Object, 1) (Line: 190)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 713)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)