📦

Funciones de Record (Record.*)

Trabaja con estructuras clave-valor en Power Query M. Los records son la base de las filas de una tabla.

Intermedio Avanzado
🆕

Crear y Acceder a Records

Record literal — [ ]

Principiante

Sintaxis

[ campo1 = valor1, campo2 = valor2, ... ]

// Acceso por campo
record[NombreCampo]
record[#"Campo Con Espacios"]

¿Qué hace?

Un record en M es una colección ordenada de pares clave-valor, similar a un objeto JSON o una fila de tabla. Se crea con [ ] y se accede con record[campo].

Ejemplo

// Crear un record
let persona = [Nombre = "Sara", Edad = 30, Ciudad = "Madrid"]
in persona[Nombre]   // "Sara"

// Campos con espacios o caracteres especiales
let config = [#"Tasa de IVA" = 0.21, #"Año Fiscal" = 2024]
in config[#"Tasa de IVA"]   // 0.21

// El contexto de fila _ es un record de la fila actual
Table.AddColumn(tabla, "NombreCompleto",
    each _[Nombre] & " " & _[Apellido]
)
💡 Tip kawaii: En Power Query, cuando usas each, el _ implícito es el record de la fila actual. Por eso each [Columna] es lo mismo que each _[Columna].

Record.Field / Record.HasFields

Intermedio

Sintaxis

Record.Field(record as record, field as text) as any
Record.HasFields(record as record, fields as any) as logical

¿Qué hace?

Record.Field accede a un campo cuyo nombre se conoce en tiempo de ejecución (dinámico). Record.HasFields comprueba si el record tiene uno o varios campos.

Ejemplo

let r = [A = 1, B = 2, C = 3]
in Record.Field(r, "B")   // 2

// Acceso dinámico (útil cuando el nombre de campo viene de una variable)
let
    campoDeseado = "Ciudad",
    persona = [Nombre = "Ana", Ciudad = "Barcelona"]
in Record.Field(persona, campoDeseado)   // "Barcelona"

// Comprobar existencia de campo
Record.HasFields([A=1, B=2], "C")        // false
Record.HasFields([A=1, B=2], {"A","B"})  // true (comprueba varios a la vez)
🗂️

Campos y Valores

Record.FieldNames / Record.FieldValues

Intermedio

Sintaxis

Record.FieldNames(record as record) as list
Record.FieldValues(record as record) as list
Record.FieldCount(record as record) as number

¿Qué hace?

Extraen los nombres de campo, los valores o el número de campos de un record, respectivamente. Útiles para introspección y procesamiento dinámico.

Ejemplo

let r = [Nombre = "Ana", Edad = 25, Ciudad = "BCN"]
in [
    nombres  = Record.FieldNames(r),   // {"Nombre", "Edad", "Ciudad"}
    valores  = Record.FieldValues(r),  // {"Ana", 25, "BCN"}
    cantidad = Record.FieldCount(r)    // 3
]

// Obtener nombres de columnas de la primera fila de una tabla
Record.FieldNames(tabla{0})

Record.ToList / Record.ToTable

Intermedio

Sintaxis

Record.ToList(record as record) as list
Record.ToTable(record as record) as table

¿Qué hace?

Record.ToList convierte los valores del record a lista. Record.ToTable convierte el record a una tabla de dos columnas: Name y Value.

Ejemplo

let r = [A = 10, B = 20, C = 30]
in Record.ToList(r)    // {10, 20, 30}

Record.ToTable([Pais = "ES", Año = 2024])
// Tabla:
// Name  | Value
// ------+------
// Pais  | "ES"
// Año   | 2024
🧠

Modificar Records

Record.AddFields / Record.RemoveFields

Intermedio

Sintaxis

Record.AddFields(record as record, fields as record) as record
Record.RemoveFields(record as record, fields as any) as record
Record.RenameFields(record as record, renames as list) as record

¿Qué hace?

Añade, elimina o renombra campos de un record sin modificar el original (M es inmutable). Devuelve un nuevo record con los cambios aplicados.

Ejemplo

let base = [Nombre = "Ana", Edad = 25]
in [
    // Añadir campo
    conCiudad  = Record.AddFields(base, [Ciudad = "Madrid"]),
    // [Nombre = "Ana", Edad = 25, Ciudad = "Madrid"]

    // Eliminar campo
    sinEdad    = Record.RemoveFields(base, "Edad"),
    // [Nombre = "Ana"]

    // Renombrar campo
    renombrado = Record.RenameFields(base, {{"Nombre", "Name"}, {"Edad", "Age"}})
    // [Name = "Ana", Age = 25]
]

Record.TransformFields

Avanzado

Sintaxis

Record.TransformFields(record as record, transformOperations as list, optional missingField as nullable number) as record

¿Qué hace?

Aplica transformaciones a campos específicos de un record. Cada operación es un par {nombreCampo, función}.

Ejemplo

let r = [Nombre = "ana garcía", Precio = "1234.5", Activo = "true"]
in Record.TransformFields(r, {
    {"Nombre",  Text.Proper},
    {"Precio",  Number.FromText},
    {"Activo",  Logical.FromText}
})
// [Nombre = "Ana García", Precio = 1234.5, Activo = true]
🔗

Combinar Records

Record.Combine

Intermedio

Sintaxis

Record.Combine(records as list) as record

¿Qué hace?

Fusiona una lista de records en uno solo. Si hay campos con el mismo nombre, el último valor prevalece.

Ejemplo

Record.Combine({
    [Nombre = "Ana", Edad = 25],
    [Ciudad = "Madrid", Pais = "ES"],
    [Edad = 26]   // sobreescribe Edad
})
// [Nombre = "Ana", Edad = 26, Ciudad = "Madrid", Pais = "ES"]

// Patrón: record de configuración por defecto + sobrescribir con parámetros
let
    defaults = [Timeout = 30, Reintentos = 3, Debug = false],
    params   = [Timeout = 60, Debug = true]
in Record.Combine({defaults, params})
// [Timeout = 60, Reintentos = 3, Debug = true]
💡 Tip kawaii: El patrón "defaults + overrides" con Record.Combine es muy útil para funciones personalizadas con muchos parámetros opcionales. Defines los valores por defecto y sólo el usuario sobrescribe los que necesita cambiar.
🔄

Convertir Records

Record.FromList / Record.FromTable

Intermedio

Sintaxis

Record.FromList(list as list, fields as any) as record
Record.FromTable(table as table) as record

¿Qué hace?

Record.FromList crea un record desde una lista de valores y una lista de nombres de campo. Record.FromTable crea un record desde una tabla con columnas Name y Value.

Ejemplo

// Desde lista
Record.FromList({"Ana", 25, "Madrid"}, {"Nombre", "Edad", "Ciudad"})
// [Nombre = "Ana", Edad = 25, Ciudad = "Madrid"]

// Desde tabla de parámetros (patrón muy usado en PQ)
let
    tablaParams = #table({"Name", "Value"}, {
        {"Servidor", "prodserver"},
        {"BaseDatos", "ventas"},
        {"Puerto", 1433}
    }),
    config = Record.FromTable(tablaParams)
in config[Servidor]   // "prodserver"
📌 Buena práctica: El patrón de tabla de parámetros + Record.FromTable es la forma estándar de gestionar configuración en Power Query. Crea una tabla llamada "Parametros" con columnas Name/Value y conviértela a record para acceder a los valores por nombre.
🔮

Patrones Prácticos

Filas como Records — tabla{n} y Table.First

Intermedio

¿Qué hace?

En M, cada fila de una tabla es un record. Puedes acceder a una fila específica con tabla{indice} (base 0) o con Table.First. Esto es muy útil para leer valores de tablas de parámetros.

Ejemplo

let tabla = #table({"Nombre","Valor"}, {{"IVA", 0.21}, {"IRPF", 0.15}})
in [
    // Acceder a la primera fila como record
    primeraFila = tabla{0},           // [Nombre = "IVA", Valor = 0.21]

    // Acceder a un campo de la primera fila
    iva = tabla{0}[Valor],            // 0.21

    // Buscar por condición
    irpf = tabla{[Nombre = "IRPF"]}[Valor]  // 0.15 (búsqueda por campo)
]
💡 Tip kawaii: La sintaxis tabla{[Campo = "valor"]}[OtroCampo] es como un BUSCARV de M: busca la fila donde Campo = "valor" y devuelve el valor de OtroCampo. ¡Mucho más limpio que un join completo!
🚀 ¡Records dominados! Ahora explora las Funciones de Transformación para combinadores, comparadores y separadores avanzados.