Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Level up your Power BI skills this month - build one visual each week and tell better stories with data! Get started

Reply
Syndicate_Admin
Administrator
Administrator

Error de firewall de fórmulas: problema de la API de Business Central

Hola comunidad. Perdóname si mi inglés no es bueno, el inglés no es mi primer idioma.

Mi empleador actual implementó Business Central (Web) para que el ERP administre la empresa y tengo una buena cantidad de brechas en el lado de la API y la estructura de BC, pero hay 3 API principales disponibles cuando conecto Power BI a BC: WebServices (heredado), API avanzadas y API estándar v2.0.

KedielSanchez_1-1744662155963.png

Y tenemos varias empresas, por lo que los informes deben funcionar como una solución de consolidación.

KedielSanchez_2-1744662461386.png

KedielSanchez_7-1744663359341.png

El problema comienza cuando intento usar una función personalizada para unir varias tablas desde cualquiera de las API. Esta es una consulta que da como resultado el error de firewall:

let
    Receta_fx = (Empresas as text) =>
    let
        Origen = Dynamics365BusinessCentral.ApiContentsWithOptions(null, null, null, null),
        IGC_CONF = Origen{[Name="PRODUCTION"]}[Data],
        TESTPBI = IGC_CONF{[Name=Empresas]}[Data],
        WebServices = TESTPBI{[Name="WebServices"]}[Data],
        Receta_table = WebServices{[Name="Receta",Signature="table"]}[Data],
        RecetaProdBOMLine = Table.ExpandTableColumn(Receta_table, "RecetaProdBOMLine", {"Production_BOM_No", "Version_Code", "Line_No", "Type", "No", "Variant_Code", "Description", "Calculation_Formula", "Length", "Width", "Depth", "Weight", "Quantity_per", "Unit_of_Measure_Code", "Scrap_Percent", "Routing_Link_Code", "Position", "Position_2", "Position_3", "Lead_Time_Offset", "Starting_Date", "Ending_Date", "Receta", "Production_BOM_No_Link"}, {"Production_BOM_No", "Version_Code", "Line_No", "Type", "No.1", "Variant_Code", "Description.1", "Calculation_Formula", "Length", "Width", "Depth", "Weight", "Quantity_per", "Unit_of_Measure_Code.1", "Scrap_Percent", "Routing_Link_Code", "Position", "Position_2", "Position_3", "Lead_Time_Offset", "Starting_Date", "Ending_Date", "Receta", "Production_BOM_No_Link"})
    in
        RecetaProdBOMLine,
    Source = Table.SelectColumns( Companies, {"Company"}),
    CustFunct_Receta_fx = Table.AddColumn(Source, "Receta_Table_fx", each Receta_fx([Company]))
in
    CustFunct_Receta_fx

KedielSanchez_3-1744662653289.png

Y si coloco la función como una consulta independiente, todavía recibo el error Formula Firewall incluso cuando el nivel de privacidad se establece en Organizacional en todas las consultas.

let
    Source = Companies,
    #"Removed Other Columns" = Table.SelectColumns(Source,{"Company"}),
    #"Invoked Custom Function" = Table.AddColumn(#"Removed Other Columns", "Receta", each Receta_fx_([Company]))
in
    #"Invoked Custom Function"

KedielSanchez_5-1744663049343.png

KedielSanchez_6-1744663083679.png

Lo mismo para intentar unir dos consultas de diferentes API. Otra cosa extraña es que el informe se puede actualizar en el servicio Power BI.

Si no hay una solución, tendré que construir una tabla para cada empresa para cualquiera de las mesas necesarias. Esto hará que sea más difícil de mantener en el escritorio si esto no se resuelve.

1 ACCEPTED SOLUTION
Syndicate_Admin
Administrator
Administrator

Lamento mucho la demora en responder @v-priyankata.

Repasemos cada sugerencia:

1. Todas las consultas tenían el mismo nivel de privacidad establecido que Organizacional, por lo que no hay mucho que cambiar allí. Incluso probé como Público y Ninguno para ver si esa era la solución, pero no hay dados.

Asegúrese de que todas las fuentes de datos tengan el mismo nivel de privacidad para hacer esto: Vaya a Opciones y configuración de > de archivos > Configuración de fuentes de datos y seleccione cada fuente de API de Business Central y haga clic en Editar permisos Establezca todos ellos en Organización (preferiblemente si todos son internos)
2. Lo intenté al principio. Ya sea que la función se use como una consulta independiente o solo como un paso en la consulta final, el error aún se activa, incluso con los niveles de privacidad establecidos en Organizacional.

Si hace referencia a una consulta dentro de otra, esto puede activar el firewall. En su lugar, cargue los datos de cada origen en consultas de ensayo independientes y combine o anexe los datos después (todo dentro del mismo nivel de privacidad).
3. Lo intenté y fallé.

Como solución temporal (no recomendada para producción), vaya a Opciones y configuración de > de archivos > Opciones > Privacidad de > de archivos actuales Establézcalo en
"Ignorar siempre la configuración del nivel de privacidad".
4. Desafortunadamente, no tengo los conocimientos para construir uno, y la empresa tampoco tiene a nadie con esa capacidad.

Considere usar un conector personalizado para un uso más avanzado de la API (como recuperar datos en varias empresas a través de funciones), un conector personalizado puede manejar esta lógica de una manera más segura y escalable.


Aproximación final

Al final del día, tuve que deshacerme de la función que tiraba dinámicamente de la mesa de cualquier empresa. En cambio, creé una consulta estandarizada paso a paso que me permite dirigirme a cualquier empresa de la organización. También creé un método no estándar para extraer los nombres y tipos de columna del esquema de tabla.

Usaré el método

VendorLedgerEntries 

como ejemplo de la API de servicios web.


Consulta auxiliar:

Esta consulta se conecta a Business Central, navega a la empresa y la tabla específicas y extrae una lista de los nombres de columna y sus respectivos tipos en un formato que luego se puede reutilizar en otras consultas.

// ColType_and_ColName_of_AnyTable

let
// Connect to the Business Central environment
Source = Dynamics365BusinessCentral.ApiContentsWithOptions(null, null, null, null),
// Select the PRODUCTION environment
PRODUCTION = Table.SelectRows(Source, each [Name]="PRODUCTION"),
// Get the list of companies in that environment
CompaniesList = PRODUCTION[Data]{0},
// Select a specific company
Companies = Table.SelectRows(CompaniesList, each [Name] = "NameOfCompany"),
// Load all APIs available for the selected company
APIsList = Companies[Data]{0},
// Filter the API group containing the table (WebServices in this case)
API = Table.SelectRows(APIsList, each [Name]="WebServices"),
// Load the list of available tables
TableList = API[Data]{0},
// Filter the desired table
TableSel = Table.SelectRows(TableList, each ([Name] = "VendorLedgerEntries")),
// Load the actual data of the table (not yet expanded)
Table = TableSel[Data]{0},
// Get the metadata (schema) of the table and filter out problematic types like Table.Type or Record.Type
TableMetadata = Table.SelectRows(
Table.Schema(Table),
each [Name] <> "ETag" and not (List.Contains({"Table.Type", "Record.Type"}, [TypeName]))
),
// Create a helper column with format { "ColumnName", ColumnType } as string
Helper_ColType = Table.AddColumn(
TableMetadata,
"Helper",
each Text.Combine({"{", Character.FromNumber(34)&[Name]&Character.FromNumber(34), ", ", [TypeName], "}"})
),
// Create another helper column just with the column names as strings
Helper_Col = Table.AddColumn(
Helper_ColType,
"Helper_ColName",
each Text.Combine({Character.FromNumber(34), [Name], Character.FromNumber(34)})
),
// Create a string that can be pasted in a Table.TransformColumnTypes step
String_ColType = "{" & Text.Combine(Helper_Col[Helper], ", ") & "}",
// Create a string with just the column names for use in ExpandTableColumn
Sting_ColName = "{" & Text.Combine(Helper_Col[Helper_ColName], ", ") & "}",
// Combine both strings with line breaks for easy pasting
String = Text.Combine({Sting_ColName, Character.FromNumber(10), Character.FromNumber(10), String_ColType})
in
String

KedielSanchez_0-1753974943101.png


Consulta principal:
Esta consulta navega dinámicamente por la estructura de Business Central, selecciona una o varias empresas, busca la tabla y expande los datos utilizando los nombres y tipos de columna extraídos por la consulta auxiliar anterior.

// VendorLedgerEntries


let
// Connect to Business Central root
Source = Dynamics365BusinessCentral.ApiContentsWithOptions(null, null, null, null),
// Select the PRODUCTION environment
PRODUCTION = Table.SelectRows(Source, each [Name]="PRODUCTION"),
// Get the list of companies in the environment
CompaniesList = PRODUCTION[Data]{0},
// Filter desired company or companies (one or many depending on setup)
CompanieSel = Table.SelectRows(CompaniesList, each [Name] = "CompanyName"),
// To query multiple companies, just duplicate and OR multiple [Name] conditions
// Rename columns for clarity
Companies = Table.RenameColumns(
Table.SelectColumns(CompanieSel, {"Name", "Data"}),
{{"Name", "Compañía"}, {"Data", "APIs"}}
),
// Expand APIs available for each company
APIsList = Table.ExpandTableColumn(Companies, "APIs", Table.ColumnNames(Companie[APIs]{0})),
// Filter the API group to only WebServices
APISel = Table.SelectRows(APIsList, each [Name]="WebServices"),
// Rename columns again for clarity
API = Table.RenameColumns(
Table.SelectColumns(APISel, {"Compañía", "Data"}),
{"Data", "Tables"}
),
// Expand list of tables in WebServices
TableList = Table.ExpandTableColumn(API, "Tables", Table.ColumnNames(API[Tables]{0})),
// Select the target table: VendorLedgerEntries
TableSel = Table.SelectRows(TableList, each ([Name] = "VendorLedgerEntries")),
// Rename column to make it clear where the actual data is
Table = Table.RenameColumns(
Table.SelectColumns(TableSel, {"Compañía", "Data"}),
{"Data", "TableData"}
),
// Expand table data using column names from the helper query (paste upper part of helper)
Table_Data = Table.ExpandTableColumn(
Table,
"TableData",
/* Paste the list of column names from the helper query output */
),
// Apply correct column types using the second part of the helper query (paste bottom part of helper)
NativeColType = Table.TransformColumnTypes(
Table_Data,
/* Paste the list of { "ColumnName", Type } pairs from the helper query output */
)
in
NativeColType

View solution in original post

7 REPLIES 7
Syndicate_Admin
Administrator
Administrator

Lamento mucho la demora en responder @v-priyankata.

Repasemos cada sugerencia:

1. Todas las consultas tenían el mismo nivel de privacidad establecido que Organizacional, por lo que no hay mucho que cambiar allí. Incluso probé como Público y Ninguno para ver si esa era la solución, pero no hay dados.

Asegúrese de que todas las fuentes de datos tengan el mismo nivel de privacidad para hacer esto: Vaya a Opciones y configuración de > de archivos > Configuración de fuentes de datos y seleccione cada fuente de API de Business Central y haga clic en Editar permisos Establezca todos ellos en Organización (preferiblemente si todos son internos)
2. Lo intenté al principio. Ya sea que la función se use como una consulta independiente o solo como un paso en la consulta final, el error aún se activa, incluso con los niveles de privacidad establecidos en Organizacional.

Si hace referencia a una consulta dentro de otra, esto puede activar el firewall. En su lugar, cargue los datos de cada origen en consultas de ensayo independientes y combine o anexe los datos después (todo dentro del mismo nivel de privacidad).
3. Lo intenté y fallé.

Como solución temporal (no recomendada para producción), vaya a Opciones y configuración de > de archivos > Opciones > Privacidad de > de archivos actuales Establézcalo en
"Ignorar siempre la configuración del nivel de privacidad".
4. Desafortunadamente, no tengo los conocimientos para construir uno, y la empresa tampoco tiene a nadie con esa capacidad.

Considere usar un conector personalizado para un uso más avanzado de la API (como recuperar datos en varias empresas a través de funciones), un conector personalizado puede manejar esta lógica de una manera más segura y escalable.


Aproximación final

Al final del día, tuve que deshacerme de la función que tiraba dinámicamente de la mesa de cualquier empresa. En cambio, creé una consulta estandarizada paso a paso que me permite dirigirme a cualquier empresa de la organización. También creé un método no estándar para extraer los nombres y tipos de columna del esquema de tabla.

Usaré el método

VendorLedgerEntries 

como ejemplo de la API de servicios web.


Consulta auxiliar:

Esta consulta se conecta a Business Central, navega a la empresa y la tabla específicas y extrae una lista de los nombres de columna y sus respectivos tipos en un formato que luego se puede reutilizar en otras consultas.

// ColType_and_ColName_of_AnyTable

let
// Connect to the Business Central environment
Source = Dynamics365BusinessCentral.ApiContentsWithOptions(null, null, null, null),
// Select the PRODUCTION environment
PRODUCTION = Table.SelectRows(Source, each [Name]="PRODUCTION"),
// Get the list of companies in that environment
CompaniesList = PRODUCTION[Data]{0},
// Select a specific company
Companies = Table.SelectRows(CompaniesList, each [Name] = "NameOfCompany"),
// Load all APIs available for the selected company
APIsList = Companies[Data]{0},
// Filter the API group containing the table (WebServices in this case)
API = Table.SelectRows(APIsList, each [Name]="WebServices"),
// Load the list of available tables
TableList = API[Data]{0},
// Filter the desired table
TableSel = Table.SelectRows(TableList, each ([Name] = "VendorLedgerEntries")),
// Load the actual data of the table (not yet expanded)
Table = TableSel[Data]{0},
// Get the metadata (schema) of the table and filter out problematic types like Table.Type or Record.Type
TableMetadata = Table.SelectRows(
Table.Schema(Table),
each [Name] <> "ETag" and not (List.Contains({"Table.Type", "Record.Type"}, [TypeName]))
),
// Create a helper column with format { "ColumnName", ColumnType } as string
Helper_ColType = Table.AddColumn(
TableMetadata,
"Helper",
each Text.Combine({"{", Character.FromNumber(34)&[Name]&Character.FromNumber(34), ", ", [TypeName], "}"})
),
// Create another helper column just with the column names as strings
Helper_Col = Table.AddColumn(
Helper_ColType,
"Helper_ColName",
each Text.Combine({Character.FromNumber(34), [Name], Character.FromNumber(34)})
),
// Create a string that can be pasted in a Table.TransformColumnTypes step
String_ColType = "{" & Text.Combine(Helper_Col[Helper], ", ") & "}",
// Create a string with just the column names for use in ExpandTableColumn
Sting_ColName = "{" & Text.Combine(Helper_Col[Helper_ColName], ", ") & "}",
// Combine both strings with line breaks for easy pasting
String = Text.Combine({Sting_ColName, Character.FromNumber(10), Character.FromNumber(10), String_ColType})
in
String

KedielSanchez_0-1753974943101.png


Consulta principal:
Esta consulta navega dinámicamente por la estructura de Business Central, selecciona una o varias empresas, busca la tabla y expande los datos utilizando los nombres y tipos de columna extraídos por la consulta auxiliar anterior.

// VendorLedgerEntries


let
// Connect to Business Central root
Source = Dynamics365BusinessCentral.ApiContentsWithOptions(null, null, null, null),
// Select the PRODUCTION environment
PRODUCTION = Table.SelectRows(Source, each [Name]="PRODUCTION"),
// Get the list of companies in the environment
CompaniesList = PRODUCTION[Data]{0},
// Filter desired company or companies (one or many depending on setup)
CompanieSel = Table.SelectRows(CompaniesList, each [Name] = "CompanyName"),
// To query multiple companies, just duplicate and OR multiple [Name] conditions
// Rename columns for clarity
Companies = Table.RenameColumns(
Table.SelectColumns(CompanieSel, {"Name", "Data"}),
{{"Name", "Compañía"}, {"Data", "APIs"}}
),
// Expand APIs available for each company
APIsList = Table.ExpandTableColumn(Companies, "APIs", Table.ColumnNames(Companie[APIs]{0})),
// Filter the API group to only WebServices
APISel = Table.SelectRows(APIsList, each [Name]="WebServices"),
// Rename columns again for clarity
API = Table.RenameColumns(
Table.SelectColumns(APISel, {"Compañía", "Data"}),
{"Data", "Tables"}
),
// Expand list of tables in WebServices
TableList = Table.ExpandTableColumn(API, "Tables", Table.ColumnNames(API[Tables]{0})),
// Select the target table: VendorLedgerEntries
TableSel = Table.SelectRows(TableList, each ([Name] = "VendorLedgerEntries")),
// Rename column to make it clear where the actual data is
Table = Table.RenameColumns(
Table.SelectColumns(TableSel, {"Compañía", "Data"}),
{"Data", "TableData"}
),
// Expand table data using column names from the helper query (paste upper part of helper)
Table_Data = Table.ExpandTableColumn(
Table,
"TableData",
/* Paste the list of column names from the helper query output */
),
// Apply correct column types using the second part of the helper query (paste bottom part of helper)
NativeColType = Table.TransformColumnTypes(
Table_Data,
/* Paste the list of { "ColumnName", Type } pairs from the helper query output */
)
in
NativeColType

Syndicate_Admin
Administrator
Administrator

Hola @KedielSanchez,

Agradecemos su participación en el foro de la comunidad de Microsoft Fabric.

¿Podría compartir algunos detalles adicionales para ayudar a reducir el problema? para que podamos tratar de dar la solución.
1. ¿Qué versión de Power BI Desktop está utilizando?
2. ¿Se conecta a Business Central Online o a una instancia local?
3. ¿El error se produce con todas las API (WebServices, Advanced, Standard v2.0) o solo con algunas específicas?

Gracias.

¡Hola @v-priyankata ! Gracias por tu mensaje.

1. Marzo 2025

KedielSanchez_0-1745352074880.png

2. En línea

3. Todas las API. Replica el problema si utilizo una función personalizada

Hola @KedielSanchez
Gracias por ponerse en contacto con la comunidad de Microsoft Fabric Forum. El error Formula.Firewall suele producirse cuando Power BI aplica niveles de privacidad de datos entre consultas u orígenes de datos, especialmente cuando se combina el acceso dinámico a datos a través de funciones personalizadas o parámetros de consulta. Tenga en cuenta los siguientes pasos:

  • Asegúrese de que todas las fuentes de datos tengan el mismo nivel de privacidad para hacer esto Vaya a Opciones y configuración de > de archivos > Configuración de fuentes de datos y Seleccione cada fuente de API de Business Central y haga clic en Editar permisos Establézcalos todos en Organizacional (preferible si todos son internos)
  • Si hace referencia a una consulta dentro de otra, esto puede desencadenar el firewall. En su lugar, cargue los datos de cada origen en consultas de ensayo independientes y combine o anexe los datos después (todo dentro del mismo nivel de privacidad).
  • Como solución temporal (no recomendada para producción), vaya a Opciones y configuración de > de archivos > Opciones > Archivo actual > Privacidad Establézcalo en
    "Ignorar siempre la configuración del nivel de privacidad".
  • Considere la posibilidad de usar un conector personalizado para un uso más avanzado de la API (como la recuperación de datos de varias empresas a través de funciones), un conector personalizado puede manejar esta lógica de una manera más segura y escalable.

Si esta información es útil, por favor "Aceptar como solución" y da un "felicito" para ayudar a otros miembros de la comunidad a resolver problemas similares de manera más eficiente.
Gracias.

Hola @KedielSanchez

¿Puedo preguntarle si ha resuelto este problema? Si es así, marque la respuesta útil y acéptela como la solución. Esto será útil para que otros miembros de la comunidad que tengan problemas similares lo resuelvan más rápido.

Gracias.

Hola @KedielSanchez
Quería comprobar si ha tenido la oportunidad de revisar la información proporcionada. No dude en ponerse en contacto con nosotros si tiene más preguntas. Si mi respuesta ha abordado su consulta, acéptela como una solución y dé un 'Felicitaciones' para que otros miembros puedan encontrarla fácilmente.
Gracias.

Hola @KedielSanchez
Espero que esta información sea útil. Por favor, hágamelo saber si tiene más preguntas o si desea discutir esto más a fondo. Si esto responde a su pregunta, acéptelo como una solución y dele un 'Felicitaciones' para que otros puedan encontrarlo fácilmente.
Gracias.

Helpful resources

Announcements
April Power BI Update Carousel

Power BI Monthly Update - April 2026

Check out the April 2026 Power BI update to learn about new features.

Fabric SQL PBI Data Days

Data Days 2026 coming soon!

Sign up to receive a private message when registration opens and key events begin.

New to Fabric survey Carousel

New to Fabric Survey

If you have recently started exploring Fabric, we'd love to hear how it's going. Your feedback can help with product improvements.

Power BI DataViz World Championships carousel

Power BI DataViz World Championships - June 2026

A new Power BI DataViz World Championship is coming this June! Don't miss out on submitting your entry.