TGViewer
Channel Public Channel
Для тех, кто в танке

Для тех, кто в танке

@pbi_pq_from_tank

Канал создан для себя, обсуждаем вопросы использования языка M и шарим всякие полезные ссылки.
На вопросы отвечаем в комментах и тут - t.me/pbi_pq_from_tank_chat

Для желающих поддержать канал - https://sponsr.ru/pq_m_buchlotnik/
Subscribers
3.69K
Photos
16
Videos
2
Links
245
Recent Posts 20 shown
Post #375 517
Читаем спецификацию 12 – поиск и безопасное извлечение (item-selection & optional access)
#АнатомияФункций - #ЧитаемСпецификацию

Чтобы добить тему access осталось рассмотреть две вещи - поиск элемента (item-selection) и что делать, когда обращаться не к чему (optional access), по этому поводу код:

let
список = {1,2,3},
запись = [a=1,b=2,c=3],
таблица = #table({"a","b","c"},{{1,2,3},{4,5,6},{7,2,9}}),

// поиск элемента - item-selection - работает только для таблиц
поиск = таблица{[a=4]}, // [a=4,b=5,c=6] - вернулась вторая строка в виде записи, точнее - строка, у которой поле а равно 4
поиск1 = таблица{[b=2]}, //ошибка - найдено более одной строки (первая и третья)
поиск2 = таблица{[b=2,c=3]}, // [a=1,b=2,c=3] - но можно искать сразу по нескольким полям - и ошибки нет

// а если нету? - optional access
ошибка_с = список{4}, // error - элементов в перечислении недостаточно
не_ошибка_с = список{4}?, // null - элемента нет, но оно и не упало
ошибка_з = запись[d], // error - поле записи не найдено
не_ошибка_з = запись[d]?, // null - поля нет, но и ошибки нет
ошибка_т = таблица{[a=99]}, // error - строка не найдена
не_ошибка_т = таблица{[a=99]}?, // null - опциональный поиск строки
ошибка_п = запись[[a],[d]], //error - поле записи не найдено
не_ошибка_п = запись[[a],[d]]?, //[a=1,d=null] - проекция сохраняет тип записи,но поля нет - оно добавляется )))

// комбинация - когда цепочка обращений
ошибка_к = таблица{3}[d], // error - элементов недостаточно (нет 4-й строки)
ошибка_к1 = таблица{3}?[d], // error - не удается применить доступ к полям, так как слева уже null!
не_ошибка_к = таблица{3}?[d]? // null - вот так, ставим вопросы для каждого оператора
in
не_ошибка_к


Надеюсь, было полезно.
Всех благ!
@buchlotnik
  • 👍 17
  • 🔥 10
  • ❤ 1
Post #374 632
Разрыв мозга или снова контейнеры (часть 1)
#АнатомияФункций – алгоритмы
 
Всем привет!
В чат подкинули задачку задачу – про контейнеры и не только. По этому поводу записано два видео.
Код первой части выглядит так:
let
    f=(x)=>Excel.CurrentWorkbook(){[Name=x]}[Content],
   
    g=(len,lst)=>(optional x)=>[
            i=if x=null then 0 else x[i]+1,
            val=lst{i}?,
            outl=if x=null then List.Repeat({{}},len) else x[rep],
            min=List.Min(outl,null,List.Count),
            pos=List.PositionOf(outl,min),
            rep=List.ReplaceRange(outl,pos,1,{outl{pos}&val})
    ],
   
    w=(from,max,aq)=>[
        from=Table.Sort(from,{{"Рейтинг",Order.Descending},"Pr_id","pair"}),
        m=Number.RoundUp(Table.RowCount(from)/max),
        lst=((a)=>List.Zip({a,List.Skip(a)&{1},List.Positions(a)}))(List.Buffer(from[pair])),
        tr = List.Buffer(List.RemoveNulls(List.Transform(lst,(x)=> if x{0}=2 then null else if x{1}=2 then {x{2},x{2}+1} else {x{2}}))),
        gen=List.Last(List.Generate(g(m,tr),(x)=>x[val]<>null,g(m,tr))),
        grps=List.Buffer(gen[rep]),
 
        tr1 = List.Buffer(List.Transform(List.Sort(List.TransformMany({1..m},(x)=>grps{x-1},(x,y)=>y meta [num=x])),(x)=>Value.Metadata(x)[num])),
        add=Table.AddIndexColumn(from,"group"),
        to=Table.TransformColumns(add,{"group",(x)=>tr1{x}})
    ][to],
   
    aq = Table.FirstValue(f("aq")),
    max = Table.FirstValue(f("max")),
    from = Table.Combine(Table.Group(f("prod"),{"Pr_id","Модель","Бокс"},{"tmp",(x)=>((a)=>Table.AddIndexColumn(a,"pair",1,if a[Пары]={1,2} then 1 else 0))(Table.Sort(x,"Пары"))})[tmp]),
    gr = Table.Group(from,{"Предмет","Модель","Бокс"},{"tmp",(x)=>w(x,max,aq)}),
    tbl = Table.Combine(gr[tmp])
in
tbl

Ну а что тут к чему смотрим на ютубе, рутубе
, а исходники (причём обеих частей) давно лежат на спонсоре
 
Лайк, коммент, подписка приветствуются )))
Надеюсь, было полезно.
Всех благ!
@buchlotnik
YouTube 81 - На М - Разрыв мозга или снова контейнеры Желающие поддержать мою деятельность: мой канал с учебными видео - https://sponsr.ru/pq_m_buchlotnik/ конкретно обзор курса по языку М - https://sponsr.ru/pq_m_buchlotnik/64449/Kurs_Power_Query_yazyk_M_001_Obshchee_Struktura_kursa Ну и мало ли интересно:…
  • 🔥 20
  • 👍 10
  • 😱 1
Post #373 1.03K
Читаем спецификацию 11 – проекция (projection)
#АнатомияФункций - #ЧитаемСпецификацию

Особый тип доступа - проекция (projection) - это не чтобы написать побольше скобок, а чтобы сохранить тип возвращаемого объекта. По этому поводу код:

let
запись = [a=1,b=2,c=3],
таблица = #table({"a","b","c"},{{1,2,3},{4,5,6}}),

//проекция - projection - возвращает тот же тип структуры, но только с указанными элементами
из_записи_p = запись[[a]], //[a=1] - запись из конкретного поля
из_записи_p1 = запись[[a],[c]], //[a=1,c=3] - или несколько полей
из_записи_p2 = запись[[c],[a]], //можно менять порядок полей

из_таблицы_p = таблица[[b]], //#table({"b"},{{2},{5}}) - таблица из одного столбца
из_таблицы_p1 = таблица[[b],[c]], //#table({"b","c"},{{2,3},{5,6}}) - или нескольких столбцов
из_таблицы_p2 = таблица[[c],[a]], //#table({"c","a"},{{3,1},{6,4}}) - и тоже порядок можно менять

комбинация = таблица[[c],[a]]{0}, //[c=3,a=1] - таблица из столбцов c и a, первая строка
комбинация1 = таблица{0}[[c],[a]] //[c=3,a=1] - то же самое, но логика иная - первая строка (запись) - из нее проекция в виде полей c и a
in
комбинация1

Надеюсь, было полезно.
Всех благ!
@buchlotnik
  • 👍 21
  • 🔥 12
  • 👏 2
  • ❤‍🔥 1
Post #372 1.33K
Читаем спецификацию 10 – извлечение данных (item & field access)
#АнатомияФункций - #ЧитаемСпецификацию

Данные мы упаковали, теперь надо их достать. Два основных варианта - по элементу (item - {}) и по полю (field - []). По этому поводу код:

let
список = {1,2,3},
запись = [a=1,b=2,c=3],
таблица = #table({"a","b","c"},{{1,2,3},{4,5,6}}),

список_списков = {{1,2,3},{4,5,6},{7,8,9}},
запись_записей = [a=[b=1,c=2],d=[e=3,f=4]],

//по элементу - item access
из_списка = список{0}, //1 - первый элемент, нумерация с нуля
из_таблицы_i = таблица{1}, //[a=4,b=5,c=6] - вторая строка, это запись

//по полю - field access
из_записи_f = запись[b], //2 - значение конкретного поля
из_таблицы_f = таблица[b], //{2,5} - весь столбец b - это список

//комбинация
из_списка_списков = список_списков{2}{0}, //7 - в третьем списке первый элемент
из_записи_записей = запись_записей[d][f], //4 - из поля d взять поле f
из_таблицы_if = таблица{1}[a], //4 - вторая строка, столбец a
из_таблицы_fi = таблица[a]{1} //4 - столбец a, вторая строка
in
из_таблицы_fi

Надеюсь, было полезно.
Всех благ!
@buchlotnik
  • 👍 23
  • 🔥 11
  • ❤ 3
Post #371 1.23K
Курс - Power Query язык M - 110 - Синтаксис – IIFE
#АнатомияФункций – курс по языку M
 
Всем привет!
В 26/27 учебном году продолжаем ежемесячные публикации в течение учебного года.

Сегодня на повестке синтаксис… Ну и не только синтаксис – скорее логика выполнения, а именно – immediately invoked function expression.

Смотрим на ютубе, а в целом блок по синтаксису ищем на спонсоре.


Надеюсь, будет полезно
Всех благ!
@buchlotnik
  • 🔥 17
  • ❤ 5
  • 👍 2
Post #370 1.6K
Читаем спецификацию 09 – пишем таблицу (table)
#АнатомияФункций - #ЧитаемСпецификацию

Для таблицы в M нет специальных скобочек, используется только встроенная функция #table. Не очень лаконично, но работает - по этому поводу код:
let
просто = #table({"список","имен","полей"},{{"список","списков","значений"},{"каждая","строка","отдельно"}}), //всё передали на списках
сложно = #table(type table [t=text,n=number,d=date],{{"a",1,#date(2026,8,25)},{"b",2,#date(2026,8,26)}}), //можно задать тип полей

слияние = #table({"a","b"},{{1,2}})&#table({"b","c"},{{2,3}}), // #table({"a","b","c"},{{1,2,null},{null,2,3}}) - одноименные поля оказываются друг под другом, отсутствующие - null

пустая = #table({},{}), //нет ни строк, ни столбцов
слияние_с_пустой = слияние&пустая, //ничего не поменялось
почти_пустая = #table({},{{}}), //нет столбцов, есть пустая строка!
слияние_с_почти_пустой = слияние&почти_пустая, //добавилась пустая строка - тут бесполезно, а для Join пригодится - запоминаем

//сравнение
столбцы = #table({"a","b"},{{1,2}}) = #table({"b","a"},{{2,1}}), //true - порядок столбцов НЕ имеет значения
строки = #table({"a","b"},{{1,2},{3,4}}) = #table({"a","b"},{{3,4},{1,2}}) //false - а вот порядок строк - имеет
in
строки


Надеюсь, было полезно.
Всех благ!
@buchlotnik
  • 👍 26
  • 🔥 15
  • ❤ 3
  • ❤‍🔥 3
Post #369 1.54K
Начинаем третий учебный год курса по языку M

 
Всем привет!
В преддверии 1 сентября докладываю:
Наполнение курса идёт своим чередом.
Сейчас в наличии 11 полных блоков (синтаксис, списки, таблицы, записи, файлы и папки, типы, блок «дополнительно», включающий всякие плюшки типа обработки ошибок, рекурсии и буферизации, блок по типам, блок по работе с датами и временем, блок по работе с текстом, блок по работе с числами и хардкорный блок по динамическим словарям, где мы написали небольшую библиотеку).
Итого сейчас имеем 115 уроков, 94,5 часа учебных видео, включающие разбор 420 функций. Впереди — финальные три блока, после которых я буду считать основной курс завершённым.

Осенью начинаем с binary/binaryformat: байты, кодировки, сигнатуры файлов, разбор форматов, передача бинарных данных и, в финале, собственный unzip.
Дальше — второй блок по таблицам и весенний «доплнительно2» с темами, которые уже требуют более тяжёлой инфраструктуры и не укладываются в обычный формат отдельных файлов-примеров.
Старт нового блока — 7 сентября.

Надеюсь кому-то будет полезно)))
Всех благ!
@buchlotnik
  • 🔥 45
  • 👍 11
  • ❤ 4
Post #368 1.48K
Читаем спецификацию 08 – пишем запись (record)
#АнатомияФункций - #ЧитаемСпецификацию

Запись - набор пар имя=значение (по-умному - полей). Чертовски полезная конструкция и по этому поводу код
let
пустая = [], // квадратные скобки
простая = [a=1,b="текст",c=true], // набор полей имя=значение
// неуник = [a=1, a=2], // ошибка! - имена полей должны быть уникальны
уник1 = [a=1,а=2], //не ошибка - вторая а - кириллица
уник2 = [a=1,A=2], //не ошибка - регистр имеет значение

вложенная = [дата=#date(2026,8,18),список={1,2,3},запись=[x=1,y=[z=3]]],
умная = [a=10,b=a*2,c=b+5], // [a=10,b=20,c=25] - на соседние поля можно ссылаться

//конкатенация
сшивка = [a=1, b=2]&[c=3], //[a=1, b=2, c=3] - поля собрались в общий набор
перезапись = [a=1, b=2]&[a=3], // [a=3, b=2] - при совпадении имен правая запись затирает левую

сравнение = [a = 1, b = 2] = [b = 2, a = 1] // true! - порядок полей НЕ имеет значения
in
сравнение


Надеюсь, было полезно.
Всех благ!
@buchlotnik
  • 👍 31
  • 🔥 19
Post #367 1.69K
Читаем спецификацию 07 – пишем список (list)
#АнатомияФункций - #ЧитаемСпецификацию

Список – альфа и омега функционального программирования. Самая простая, но и самая используемая структура данных. По этому поводу код:

let
пустой = {}, //пригодится
числа = {1,3,5}, // просто через запятую - числа
тексты = {"a","c","e"}, //тексты
солянка = {1,"a",#date(2026,8,18),{2,3}},//всё сразу
список_списков = {{1},{2,3},{4,5,6}},
перечисление = {1..10}, //от до с шагом 1
перечисление2 = {1,3..11,26,37..42}, //можно несколько
перечисление_символы = {"A".."я"}, //английская A - 65 в юникоде, русская я - 1103 - очень большой список )))

//операции
конкатенация = {1,2,3}&{4,5}, // {1,2,3,4,5} - сшивка в один
сравнение = {1,2,3} = {1,2,3}, // true - можно сравнивать
сравнение2 = {1,2,3} <> {1,3,2} // true - порядок имеет значение
in
сравнение2


Надеюсь, было полезно.
Всех благ!
@buchlotnik
  • 👍 39
  • 🔥 8
  • 👏 5
  • ❤ 1
Post #366 1.78K
Читаем спецификацию 06 – арифметика дат и времени
#АнатомияФункций - #ЧитаемСпецификацию

В Excel дата плюс один — это завтра, в M - это ошибка несоответствия типов... Всё делается через duration. По этому поводу код:
let
дата1 = #date(2026,8,11),
дата2 = #date(2026,10,5),
датавремя = #datetime(2026,8,11,12,0,0),
//разница между датами, добавление или вычитание дней - только через duration!
разница = дата1-дата2, // #duration(-55,0,0,0)
следующий_день_ош = дата1 + 1, //ошибка, так не работает!
следующий_день = дата1 + #duration(1,0,0,0), // а вот так работает
два_дня_назад = дата2 - #duration(2,0,0,0), //можно вычитать
два_дня_назад2 = дата2 - 2*#duration(1,0,0,0), //duration можно умножать/делить
// с временем аналогично
плюс_час = датавремя + #duration(0,1,0,0),
полтора_часа_назад = датавремя - #duration(0,1,30,0), //вычесть
полтора_часа_назад2 = датавремя + #duration(0,-1,-30,0), //или добавить отрицательную
до_кучи = #duration(1,12,0,0)/#duration(0,0,45,0) //сколько раз по 45 минут в полутора днях )))
in
до_кучи


Надеюсь, было полезно.
Всех благ!
@buchlotnik
  • 👍 38
  • 🔥 16
  • ❤ 1
Post #365 1.76K
Читаем спецификацию 05 – пишем длительность (duration)
#АнатомияФункций - #ЧитаемСпецификацию

В M есть специальный тип – длительность (duration). Как и даты, он создается только через встроенную функцию. Именно этот тип будет нужен для пересчётов дат и времен. По этому поводу код:
let
стандарт = #duration(1,12,30,0), // (дни, часы, минуты, секунды)
назад_в_прошлое = #duration(0,-3,0,0), // значения могут быть отрицательными!

//плюшка -любое из значений можно задать произвольно - оно само пересчитает в д/ч/м/с
только_секунды = #duration(0,0,0,86400), // просто 1 день
полтора_дня = #duration(1.5,0,0,0), // 1 день 12 часов
нулевая = #duration(0,0,0,0), // просто ноль
день = #duration(1,0,0,0), //запомним для следующего раза
мракобесие = #duration(4,-31,0,0) //4 дня минус 31 час - это 2 дня и 17 часов
in
мракобесие


Надеюсь, было полезно.
Всех благ!
@buchlotnik
  • 🔥 26
  • 👍 13
  • ❤ 3
Post #364 1.86K
Читаем спецификацию 04 – пишем дату и время
#АнатомияФункций - #ЧитаемСпецификацию

В языке M нельзя просто взять и написать дату. "2026-07-28" – в кавычках, значит это текст, 28/07/2026 – деление, даст 0,00197… ну а 28.07.2026 (без кавычек) – просто выдаст ошибку. Всё создается через встроенные функции. По этому поводу код:
let
дата = #date(2026,7,28), // (год, месяц, день)
время = #time(15,30,0), // (часы, минуты, секунды)
датавремя = #datetime(2026,7,28,15,30,0),
датаИвремя = #date(2026,7,28) & #time(15,30,0), //так тоже можно
ошибка_даты = #date(2026,2,30), //30 февраля не бывает - движок следит
конец_суток = #time(24, 0, 0), // так можно!
конец_суток_датавремя_ош = #datetime(2026,7,28,24,0,0), //а так нельзя!
конец_суток_датавремя = #datetime(2026,7,28,23,59,59.9999999), //только так - точность 100 нс
начало_времен = #datetime(1,1,1,0,0,0),
конец_времен = #datetime(9999,12,31,23,59,59.9999999),

с_поясом = #datetimezone(2026,7,28,15,30,0,3,0), // по Москве
с_поясом2 = #datetimezone(2026,7,28,15,30,0,-3,-30) // по Ньюфаундленду

in
с_поясом2


Надеюсь, было полезно.
Всех благ!
@buchlotnik
  • 👍 39
  • 🔥 16
  • 👏 2
  • ❤‍🔥 1
Post #363 1.94K
Читаем спецификацию 03 – пишем текст (text)
#АнатомияФункций - #ЧитаемСпецификацию

Текст в M — это всегда про что-то в кавычках. А вот внутри кавычек либо просто печатаем, либо засовываем всякое через #(). По этому поводу код:
let
просто = "Всем привет!", //кавычки строго двойные
кавычкиВтексте = "Он сказал: ""Поехали!""", //внутри двойная кавычка
кавычка = """", //двойная кавычка в кавычках )))
перенос = "Раз#(lf)Два", // во внешних файлах чаще #(cr,lf)
табуляция = "Раз#(tab)Два", // отобразится в интерфейсе, но не на листе
можносписком = "Раз#(lf,lf,tab)Два#(lf,tab,tab)Три",
юникод = "неразрывный пробел:#(00A0)-вот он", //можно вызывать по hex-коду
смайлик = "ботан: #(0001F913)", //hex код имеет варианты 4 или 8 символов
экранирование = "#(#)(", //если прям надо написать просто #(
конкатенация = "Power" & " " & "Query" // оператор - амперсанд
in
конкатенация


Надеюсь, было полезно.
Всех благ!
@buchlotnik
  • 👍 26
  • 🔥 20
  • ❤‍🔥 6
Post #362 2.16K
Читаем спецификацию 02 – арифметические операторы
#АнатомияФункций – #ЧитаемСпецификацию

Теперь сотворим с числами всякой арифметики:
let
    //арифметические операторы
    сложение = 2 + 2, // 4
    вычитание = 10 - 3, // 7
    умножение = 5 * 5, // 25
    деление = 10 / 3, // 3.3333333333333335
    унарныйминус= -1, //да-да, это оператор, не думайте, что я забыл про него в прошлом посте
 
    // А вот дальше операторы кончились:
    степень = Number.Power(2, 3), // 2^3 не прокатит, сорян, только так
    целочисленное_деление = Number.IntegerDivide(10, 3), // кому взгруснулось из-за отсутствия 10\3 - ставим лайк
    остаток = Number.Mod(10, 3), // 1
 
    скобки = ((2+2)*2+(3-2)*(8-3))/(11+4)  //они есть и всегда круглые )))
in
    скобки


Надеюсь, было полезно.
Всех благ!
@buchlotnik
  • 👍 34
  • 🔥 10
  • ❤ 6
Post #361 2.23K
Читаем спецификацию 01 - пишем числа (number)
#АнатомияФункций – #ЧитаемСпецификацию

Начнём с простого - как записывать числа? По этому поводу код:
let
//имеем следующие варианты:
целое = 123,
дробное = 1.23, //с ТОЧКОЙ!!!
экспонента = 2.4e5, //e - английская! эквивалентно 2.4 * 10^5 т.е. 240 000
экспонента1 = 2.4e-5, //0.000024
шестнадцатеричное = 0xff, // x- тоже английский, записано 255
шестнадцатеричное1 = 0xA0, //а это 160, можно писать в любом регистре
// а ещё можно записать не совсем числа:
бесконечность = #infinity, //подсвечивается красным - это нормально, отобразится как ∞ - потом обсудим арифметику этого
нечисло = #nan, //отобразится как NaN - это например когда 0/0

назакуску = .123 //с точки без ведущего нуля можно, а вот 123. - нельзя
in
назакуску


Надеюсь, было полезно.
Всех благ!
@buchlotnik
  • 🔥 46
  • 👍 12
  • ❤‍🔥 1
Post #359 2.1K
List.TransformMany, списки и записи
#АнатомияФункций – List.TransformMany
 
Всем привет!
В чат подкинули задачку – не то, чтобы очень сложную, но захотелось примотать List.TransformMany, а потом пришлось отказаться от него, а потом снова дописать. Короче, вышел вот такой код:
let
    f=(x)=>Record.FromList(List.Combine(Table.ToList(x,(x)=>List.Skip(x,3))),List.TransformMany(x[Код платежа],(x)=>nms,(x,y)=>x&y)),
   
    from = Excel.CurrentWorkbook(){[Name="Таблица2"]}[Content],
    nms = List.Buffer(List.Skip(Table.ColumnNames(from),3)),
    gr = Table.Buffer(Table.Group(from,"№ Товара",{"tmp",f})),
    exp = Table.ExpandRecordColumn(gr,"tmp",Record.FieldNames(Record.Combine(gr[tmp]))),
    tr = Table.TransformColumns(exp,{},(x) as nullable number => Number.From(x,"en")),
    to = Table.Sort(tr,"№ Товара")
in
    to

 
А как я дошёл до жизни такой смотрим на ютубе, рутубе, а исходники, как всегда лежат на sponsr
 
Лайк, коммент, подписка приветствуются )))
Надеюсь, было полезно.
Всех благ!
@buchlotnik
  • 🔥 24
  • 👍 10
  • ❤ 1
Post #358 1.5K
Text.Format, словари и прочие записи
#АнатомияФункций – customfunctions

 Всем привет!
В чат подкинули задачку – сложную, с блекджеком и … Text.Format. По этому поводу код:
let
    f=(x)=> Excel.CurrentWorkbook(){[Name=x]}[Content],
    fields = Record.FromTable(Table.TransformColumns(f("ins"),{{"Name",(x)=>"#"&x&"#"},{"Value",(x)=>"#["&x&"]"}})),
    g=(x)=>Text.Combine(List.Transform(
        Splitter.SplitTextByPositions({0}&List.Sort(Text.PositionOf(" "&x," #",Occurrence.All)&Text.PositionOf(" "&x,"# ",Occurrence.All)))(x),
        (x)=>Record.FieldOrDefault(fields,x,x))),
 
    dsc = Table.Buffer(Table.TransformColumns(f("dsc"),{},g)),
    formats = Record.FromList(Table.ToList(dsc,List.Skip),dsc[ТипТовара]),
    formatnms = List.Buffer(List.Skip(Table.ColumnNames(dsc))),
    pcs = Table.Buffer(Table.TransformColumns(f("pcs"),{"ПорядокЧастей",(x)=>"#["&x&"]"})),
    dscf = List.Buffer(List.Transform({0..3},(x)=>Text.Combine(Table.SelectRows(pcs,(z)=>z[ПорядокСокращения]=null or z[ПорядокСокращения]>x)[ПорядокЧастей]," "))),
    var = f("var"),
    varlst = List.Buffer(Table.ToList(var,List.Skip)),
    varnms = List.Buffer(List.Transform(var[var],(x)=>"Описание_"&x)),
    trim=(x)=>Text.Combine(List.RemoveMatchingItems(Text.Split(x," "),{""})," "),
 
    h=(x)=>[rec=x&Record.FromList(List.Transform(Record.Field(formats,x[ТипТовара]),(y)=>Text.Format(y,x)),formatnms),
            lst = List.Buffer(List.Transform(dscf,(x)=>trim(Text.Format(x,rec)))),
            trf=(x)=>[
                z=if x{1}=null then lst else List.Transform(lst,(y)=>Text.Replace(y," / ",x{1})),
                a=List.Skip(z,(y)=>Text.Length(y)>x{0}){0}?,
                b=List.Last(List.Select(Text.PositionOf(List.Last(z),".",Occurrence.All),(y)=>y<x{0}))+1,
                c=if a=null then Text.Start(List.Last(z),b) else a][c],
            to = Record.FromList(List.Transform(varlst,trf),varnms)][to],
 
    from = Table.AddColumn(f("prod10"),"tmp",h),
    to = Table.ExpandRecordColumn(from,"tmp",varnms)
in
    to

Много, сложно, но жутко интересно.
А что тут к чему смотрим на ютубе, рутубе, а исходники, как всегда лежат на sponsr
 
Лайк, коммент, подписка приветствуются )))

Надеюсь, было полезно.
Всех благ!
@buchlotnik
YouTube 79 - На М - Text.Format, словари и прочие записи Желающие поддержать мою деятельность: мой канал с учебными видео - https://sponsr.ru/pq_m_buchlotnik/ конкретно обзор курса по языку М - https://sponsr.ru/pq_m_buchlotnik/64449/Kurs_Power_Query_yazyk_M_001_Obshchee_Struktura_kursa Ну и мало ли интересно:…
  • 👍 19
  • 🔥 12
Post #356 1.52K
Читаем спецификацию 00 или каналу на sponsr 2 года
#АнатомияФункций – ЧитаемСпецификацию

Всем привет! Пропадал с радаров – немножко был занят. Пора возвращаться и разводить бурную информационную деятельность )))
По этому поводу:
- Сегодня в 15:00 выйдет анонс видео, которое лежит на ютубе уже месяц. Ну вот так вышло, мне просто важно соблюсти хронологию.
- А вот в 18:00 выйдет новое — так что не пугаемся, это не спам.

Дальше — больше. Завтра исполняется 2 года каналу на Sponsr.ru!
По этому поводу запускаю марафон «Читаем спецификацию».
Вот кроме шуток — раз в неделю буду цитировать спецификацию: от синтаксической базы до рекурсивного коллайдера. Завтра первый выпуск в непривычное, но вполне учебное время — 12:00. Так что не расслабляемся, читаем ))) В спецификации много интересного.

Ну и прямо сейчас начался летний блок по источникам данных на Sponsr . Кому интересно — заходим и приобщаемся.

Наконец, надо определиться с планами на следующий учебный год, поэтому следующим постом будет голосовалка. Мне надо понять: учебные видосы на ютубе вообще кому-нибудь интересны? Прошу проявить активность.

Как-то так, в общем. Сегодня заспамлю, а там как пойдет.

Надеюсь, будет полезно.
Всех благ!
@buchlotnik
  • 🔥 31
  • ❤ 1
Older posts →

About this channel

How can I read @pbi_pq_from_tank without a Telegram account?
TGViewer shows the public web preview Telegram publishes for Для тех, кто в танке: recent posts, photos, videos and the subscriber count, with no app, login or account.
How many subscribers does Для тех, кто в танке have?
Для тех, кто в танке (@pbi_pq_from_tank) has 3.69K subscribers on Telegram, refreshed roughly every 30 minutes.
Does Для тех, кто в танке know I viewed it here?
No. Public channel previews carry no viewer identity, and TGViewer has no accounts or tracking of what you look up.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →