Страницы: 1
RSS
Можно ли нормализовать следующую таблицу с расписанием, используя power query?
 
Имею таблицы следующего вида. Файлы во вложении

По таблице Расписание классов 0112

1. листов может быть сколько угодно (сейчас 3)
2. столбцов сколько угодно

По таблице Расписание учителей 0112
1. Всегда 2 лист. Количество учителей и уроков, конечно, может варьироваться

хотелось бы, если это возможно, нормализовать таблицу, чтобы можно было использовать функции ВПР или другие, для поиска или извлечения нужной информации
Конечно, удалить верхние стороки не проблема. А вот как всю таблицу превратить в нормализованную я не знаю.

Получить мне нужно столбцы
1 ключ (например 1_1, где первая цифра это день недели, а вторая номер урока)
2 день недели (1,2,3,4,5,6 (1 это пн, 2 это вт и т.д)
3 номер урока
4 класс
5 кабинет
6 учитель (данные в книге Расписание учителей 0112). Всегда 2 лист. Количество учителей и уроков, конечно, может варьироваться
7 предмет
8 смена 1 или 2 (если 1 урок не пустой, то 1 смена, иначе вторая)
Эти данные есть в книге Расписание классов 0112

* есть сдвоенные ячейки. Например AY15

С чего, хотя бы начать делать? Ни в одном примере ничего хотя бы близко такого, чтобы можно было нормализовать таблицу я не нашел.
 
не понятно который из них желаемый результат?
 
Доброе время суток. С наступившим Новым Годом!
Цитата
artyrH написал:
не понятно который из них желаемый результат?
Желаемый результат не представлен - как и всякий начинающий ТС, extrafant, застенчив. Предполагаю, должно получиться нечто вроде такого, естественно, порядок вывода и наименования столбцов могут различаться. В общем-то ничего сложного. Редизайн таблиц и сшивка по дню недели, номеру урока, кабинету, ну и номеру класса для страховки.
 
Желаемый результат во вложении. Получается, что чтобы его добиться, нужно собрать информацию из 2х таблиц
Редизайн, да, но на мой взгляд, не простой он, этот редизайн
Изменено: extrafant - 01.01.2020 16:25:43
 
Цитата
extrafant написал:
но на мой взгляд, не простой он, этот редизайн
Вариант для подхода создания того требуемого редизайна. Может тёзка отважится сделать нечто универсальное.
 
по моему где то я ошибся :)
Код
let
    Source = Excel.Workbook(File.Contents("C:\abc\Расписание учителей 0112.xlsx"), null, true),
    #"2_Sheet" = Source{[Item="2",Kind="Sheet"]}[Data],
    #"Removed Blank Rows" = Table.SelectRows(#"2_Sheet", each not List.IsEmpty(List.RemoveMatchingItems(Record.FieldValues(_), {"", null}))),
    #"Removed Top Rows" = Table.Skip(#"Removed Blank Rows",2),
    #"Transposed Table" = Table.Transpose(#"Removed Top Rows"),
    #"Filled Down" = Table.FillDown(#"Transposed Table",{"Column1", "Column2"}),
    #"Merged Columns" = Table.CombineColumns(Table.TransformColumnTypes(#"Filled Down", {{"Column2", type text}}, "ru-RU"),{"Column1", "Column2", "Column3"},Combiner.CombineTextByDelimiter("=", QuoteStyle.None),"Сведено"),
    #"Promoted Headers" = Table.PromoteHeaders(#"Merged Columns", [PromoteAllScalars=true]),
    #"Promoted Headers1" = Table.PromoteHeaders(#"Promoted Headers", [PromoteAllScalars=true]),
    #"Replaced Value" = Table.ReplaceValue(#"Promoted Headers1",null,0,Replacer.ReplaceValue,Table.ColumnNames( #"Promoted Headers1")),
    #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Replaced Value", {"Учитель=="}, "Атрибут", "Значение"),
    #"Split Column by Delimiter" = Table.SplitColumn(#"Unpivoted Other Columns", "Учитель==", Splitter.SplitTextByDelimiter("=", QuoteStyle.Csv), {"Учитель==.1", "Учитель==.2", "Учитель==.3"}),
    Pivoted = Table.Pivot(#"Split Column by Delimiter", List.Distinct(#"Split Column by Delimiter"[#"Учитель==.3"]), "Учитель==.3", "Значение"),
    Неделя = Table.FromRecords({[a = "Понедельник", b = 1, 1="Пн"], [a = "Вторник", b = 2, 1="Вт"],[a = "Среда", b = 3, 1="Ср"],[a = "Четверг", b = 4, 1="Чт"],[a = "Пятница", b = 5, 1="Пт"],[a = "Суббота", b = 6, 1="Сб"],[a = "Воскресенье", b = 7, 1="Вс"]}),
    #"Merged Queries" = Table.Join(Pivoted,{"Учитель==.1"},Неделя,{"a"},JoinKind.LeftOuter),
    #"Changed Type" = Table.TransformColumnTypes(#"Merged Queries",{{"Учитель==.2", Int64.Type}, {"Атрибут", type text}, {"Класс", type text}, {"Каб.", type text}, {"b", Int64.Type}}),
    #"Sorted Rows" = Table.Sort(#"Changed Type",{{"Атрибут", Order.Ascending}, {"b", Order.Ascending}, {"Учитель==.2", Order.Ascending}}),
    Removed = Table.SelectColumns(#"Sorted Rows",{"b", "Учитель==.2", "Класс", "Каб.", "Атрибут"}),

    Source2 = Excel.Workbook(File.Contents("C:\abc\Расписание классов 0112.xlsx"), null, true),
    #"Added Custom" = Table.AddColumn(Source2, "D", each Table.PromoteHeaders(Table.Skip([Data],3)))[[D]],
    #"Added Custom1" = Table.AddColumn(#"Added Custom", "a", each let
     #"Added Index" = Table.AddIndexColumn([D], "Индекс"),
    #"Added Conditional Column" = Table.AddColumn(#"Added Index", "a", each if [Column2] = 1 then [Индекс] else null),
    #"Filled Down" = Table.FillDown(#"Added Conditional Column",{"Column1", "Column2","a"}),
    #"Grouped Rows" = Table.Group(#"Filled Down", {"Column1", "Column2","a"}, {{"b", each Table.AddIndexColumn(_, "Индекс2"), type table}})[[b]],
    #"Expanded {0}" = Table.ExpandTableColumn(#"Grouped Rows", "b", Table.ColumnNames(#"Grouped Rows"[b]{0})),
    #"Merged Columns" = Table.CombineColumns(Table.TransformColumnTypes(#"Expanded {0}", {{"Column2", type text}, {"Индекс2", type text}}, "ru-RU"),{"Column1", "Column2", "Индекс2"},Combiner.CombineTextByDelimiter("=", QuoteStyle.None),"Сведено"),
    #"Removed Columns" = Table.RemoveColumns(#"Merged Columns",{"Индекс", "a"}),
    #"Reordered Columns" =Table.ReorderColumns(#"Removed Columns",{"Сведено"}&List.RemoveLastN( Table.ColumnNames(#"Removed Columns"),1)),
    #"Transposed Table" = Table.Transpose(#"Reordered Columns"),
    #"Filled Down1" = Table.FillDown(#"Transposed Table",{"Column1"}),
    #"Promoted Headers" = Table.PromoteHeaders(#"Filled Down1", [PromoteAllScalars=true]),
    #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Promoted Headers", {"День=#=0", "День=#=1"}, "Атрибут", "Значение"),
    #"Pivoted Column" = Table.Pivot(#"Unpivoted Other Columns", List.Distinct(#"Unpivoted Other Columns"[#"День=#=1"]), "День=#=1", "Значение"),
    #"Split Column by Delimiter" = Table.SplitColumn(#"Pivoted Column", "Атрибут", Splitter.SplitTextByDelimiter("=", QuoteStyle.Csv), {"Атрибут.1", "Атрибут.2", "Атрибут.3"}),
    #"Changed Type" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Атрибут.1", type text}, {"Атрибут.2", type text}, {"Атрибут.3", type text}}),
    #"Filtered Rows" = Table.SelectRows(#"Changed Type", each ([Атрибут.2] <> "#"))
in
    #"Filtered Rows")[[a]],
    Expanded = Table.ExpandTableColumn(#"Added Custom1", "a", {"День=#=0", "Атрибут.1", "Атрибут.2", "Предмет", "Каб."}),
    Custom1 = Table.Join(Expanded,{"Атрибут.1"},Неделя,{"1"},JoinKind.LeftOuter),
    #"Changed Type1" = Table.TransformColumnTypes(Custom1,{{"Атрибут.2", Int64.Type}, {"b", Int64.Type}}),
    #"Merged Queries1" = Table.NestedJoin(Removed,{"b", "Учитель==.2", "Класс","Каб."},#"Changed Type1",{"b", "Атрибут.2","День=#=0","Каб."},"Expanded",JoinKind.LeftOuter),
    #"Expanded {0}" = Table.ExpandTableColumn(#"Merged Queries1", "Expanded", {"Предмет"})
in
    #"Expanded {0}"
 
как-то так наворотил
Код
let
    f1 = (t as table,nrows as number)=> let
        OldNames   = Table.Transpose(Table.FirstN(t,nrows)),
        TmpCols    = List.Transform({1..nrows},each "Column"&Text.From(_)),
        Operations = List.Zip({TmpCols,List.Repeat({each Text.Clean(Text.Trim(Text.From(_)))},nrows)}),
        TrimClean  = List.Buffer(Table.ToRows(Table.TransformColumns(OldNames,Operations))),
        NewNames   = List.Generate(()=>
            [ i = 0,
              r = List.RemoveLastN(TrimClean{i},each _=null),
              v = r ],
            each [i]<List.Count(TrimClean),
            each [
                i = [i]+1,
                r = List.RemoveLastN(TrimClean{i},each _=null),
                v = 
                    let 
                        prev=[v] 
                    in 
                        List.Generate(()=>
                            [ i = 0,
                              s = if r{i}=null then prev{i} else  r{i}], 
                            each [i]<List.Count(r),
                            each [ i = [i]+1,
                                   s = if r{i}=null then prev{i} else r{i}], 
                            each [s]
                        )
            ],
            each Text.Combine([v],"|")
        ),
        HeadreRow  = Record.FromList(NewNames,Table.ColumnNames(t))
    in Table.PromoteHeaders(Table.InsertRows(Table.Skip(t,nrows),0,{HeadreRow})),
    f2 = (t,columns)=> let
        Unpivot  = Table.UnpivotOtherColumns(t,List.Select(Table.ColumnNames(t),each not Text.Contains(_,"|")),"Атрибут","Значение"),
        Split    = Table.SplitColumn(Unpivot, "Атрибут",each Text.Split(_,"|"),columns),
        Pivot    = Table.Pivot(Split, List.Distinct(Split[Атрибут]), "Атрибут", "Значение"),
        WeekDays = List.Transform({1..14},each Text.Proper(Date.ToText(#date(1,1,_),"ddd"&(if _>7 then "d" else ""),"ru-ru"))),
        Replace  = Table.ReplaceValue(Pivot,0,0,(a,b,c)=>Number.Mod(List.PositionOf(WeekDays,a),7)+1,{"День"})
    in Replace,
    f3 = (tbl as table)=> let
        NewHeaders = Table.FillDown(f1(Table.Skip(tbl,each [Column1]<>"День"),2),{"День"}),
        Group      = Table.Group(
            NewHeaders, 
            {"День", "#"}, 
            List.Transform(
                List.Skip(Table.ColumnNames(NewHeaders),2),
                each let s = _
                     in {s,(t)=>Replacer.ReplaceValue(List.RemoveNulls(Table.Column(t,s)),{},null)}
            ),
            0,
            (a,b)=>Number.From(b[#"#"]<>null)
        )
    in Table.ExpandListColumn(Table.ExpandListColumn(f2(Group,{"Класс","Атрибут"}), "Предмет"), "Каб."),
    Source          = Excel.Workbook(File.Contents("C:\TEMP\Расписание классов 0112.xlsx"), null, true)[[Data]],
    Source2         = Excel.Workbook(File.Contents("C:\TEMP\Расписание учителей 0112.xlsx"), null, true)[Data]{1},
    ClassSchedule   = Table.ExpandTableColumn(Table.TransformColumns(Source,{{"Data",f3}}), "Data", {"День", "#", "Класс", "Предмет", "Каб."}),
    TeacherSchedule = Table.TransformColumnTypes(f2(f1(Table.Skip(Source2,each [Column1]<>"#"),3),{"День", "Урок", "Атрибут"}),{{"Урок",type number}}),
    Nested          = Table.ExpandTableColumn(Table.NestedJoin(TeacherSchedule,{"День","Урок","Класс","Каб."},ClassSchedule,{"День","#","Класс","Каб."},""), "", {"Предмет"}),
    Sorted          = Table.Sort(Nested,{{"#", Order.Ascending}, {"День", Order.Ascending}, {"Урок", Order.Ascending}})
in
    Sorted
 
Огромное спасибо за ответы!

Я так понимаю, что без языка M не обошлось бы? Ну то есть через интерфейс просто

Что-то у меня не пошло.

Я делал так:
1. Создал новую книгу в каталоге с таблицами моими
2. Создал пустой запрос
3. В область код все скопировал

Во вкладке главная закрыть и загрузить нажал...
 
extrafant, на третьем пункте открыть Расширенный редактор и скопировать туда код вместо имеющегося.
подправить пути
 
Огромное всем спасибо! Вроде работает!

А смену я могу определить через условный столбец. Я не пробовал, но в теории должно же работать. Верно?
 
Андрей Лящук,

Уважаемый Андрей, а можно ли сделать так, чтобы он показывал и пустые уроки (пустые ячейки) сейчас он выводит в список только если у учителя есть урок
 
Оффтопик
extrafant Просто ради интереса - у вас действительно 24 Первых класса обучается? Интересно - сколько учеников в классе.
 
Цитата
DrillPipe написал:
extrafant Просто ради интереса - у вас действительно 24 Первых класса обучается? Интересно - сколько учеников в классе.
У нас новая школа. Пока разрешают держать стандарт по 30. А вообще около 35 человек норма. Бывает и под 40

Вообще да, есть даже 1Ш

Всего 100 классов
из них 1-4 - 53 класса...
 
не знаю как давно, но у нас из за нехватки школ запретили оставлять на второй год
 
Цитата
artyrH написал:
не знаю как давно, но у нас из за нехватки школ запретили оставлять на второй год
У нас разрешают. Но с "умом" и не для всех. Были трагические случаи
 
Цитата
extrafant написал:
смену я могу определить
вы  в файле хотя бы цветом выделите признак смены смены. а то  не понятно где смотреть что смена вторая.
я сам то не сделаю, но посмотреть - посмотрел бы
 
Цитата
extrafant написал:
можно ли сделать так, чтобы он показывал и пустые уроки (пустые ячейки)
Какой смысл плодить пустые ячейки? Если только для того, чтобы учителя без уроков не терялись вот вариант (выводятся только существующие уроки и по 1 пустой строке для учителей без нагрузки)
Код
let
    f1 = (t as table,nrows as number)=> let
        t          = Table.Buffer(t),
        OldNames   = Table.Transpose(Table.FirstN(t,nrows)),
        TmpCols    = List.Transform({1..nrows},each "Column"&Text.From(_)),
        Operations = List.Zip({TmpCols,List.Repeat({each Text.Clean(Text.Trim(Text.From(_)))},nrows)}),
        TrimClean  = List.Buffer(Table.ToRows(Table.TransformColumns(OldNames,Operations))),
        NewNames   = List.Generate(()=>
            [ i = 0,
              r = List.RemoveLastN(TrimClean{i},each _=null),
              v = r ],
            each [i]<List.Count(TrimClean),
            each [
                i = [i]+1,
                r = List.RemoveLastN(TrimClean{i},each _=null),
                v = 
                    let 
                        prev=[v] 
                    in 
                        List.Generate(()=>
                            [ i = 0,
                              s = if r{i}=null then prev{i} else  r{i}], 
                            each [i]<List.Count(r),
                            each [ i = [i]+1,
                                   s = if r{i}=null then prev{i} else r{i}], 
                            each [s]
                        )
            ],
            each Text.Combine([v],"|")
        ),
        HeadreRow  = Record.FromList(NewNames,Table.ColumnNames(t))
    in Table.PromoteHeaders(Table.InsertRows(Table.Skip(t,nrows),0,{HeadreRow})),
    f2 = (t,columns)=> let  
        t        = Table.Buffer(t),
        l        = List.Select(Table.ColumnNames(t),each not Text.Contains(_,"|")),
        t1       = Table.SelectColumns(Table.Distinct(t,l),l),
        Unpivot  = Table.UnpivotOtherColumns(t,List.Select(Table.ColumnNames(t),each not Text.Contains(_,"|")),"Атрибут","Значение"),
        Nested   = Table.ExpandTableColumn(Table.NestedJoin(t1,l,Unpivot,l,""),"",{"Атрибут","Значение"}),
        Split    = Table.SplitColumn(Nested, "Атрибут",each Text.Split(if _=null then "" else _,"|"),columns),
        Pivot    = Table.Pivot(Split, List.RemoveNulls(List.Distinct(Split[Атрибут])), "Атрибут", "Значение"),
        WeekDays = List.Transform({1..14},each Text.Proper(Date.ToText(#date(1,1,_),"ddd"&(if _>7 then "d" else ""),"ru-ru"))),
        Replace  = Table.ReplaceValue(Pivot,0,0,(a,b,c)=>Number.Mod(List.PositionOf(WeekDays,a),7)+1,{"День"})
    in Replace,
    f3 = (tbl as table)=> let
        NewHeaders = Table.FillDown(f1(Table.Skip(tbl,each [Column1]<>"День"),2),{"День"}),
        Group      = Table.Group(
            NewHeaders, 
            {"День", "#"}, 
            List.Transform(
                List.Skip(Table.ColumnNames(NewHeaders),2),
                each let s = _
                     in {s,(t)=>Replacer.ReplaceValue(List.RemoveNulls(Table.Column(t,s)),{},null)}
            ),
            0,
            (a,b)=>Number.From(b[#"#"]<>null)
        )
    in Table.ExpandListColumn(Table.ExpandListColumn(f2(Group,{"Класс","Атрибут"}), "Предмет"), "Каб."),
    Source          = Excel.Workbook(File.Contents("C:\TEMP\Расписание классов 0112.xlsx"), null, true)[[Data]],
    Source2         = Excel.Workbook(File.Contents("C:\TEMP\Расписание учителей 0112.xlsx"), null, true)[Data]{1},
    ClassSchedule   = Table.ExpandTableColumn(Table.TransformColumns(Source,{{"Data",f3}}), "Data", {"День", "#", "Класс", "Предмет", "Каб."}),
    TeacherSchedule = Table.TransformColumnTypes(f2(f1(Table.RemoveLastN(Table.Skip(Source2,each [Column1]<>"#"),each [Column1]=null),3),{"День", "Урок", "Атрибут"}),{{"Урок",type number}}),
    Nested          = Table.ExpandTableColumn(Table.NestedJoin(TeacherSchedule,{"День","Урок","Класс","Каб."},ClassSchedule,{"День","#","Класс","Каб."},""), "", {"Предмет"}),
    Sort          = Table.Sort(Nested,{{"#", Order.Ascending}, {"День", Order.Ascending}, {"Урок", Order.Ascending}})
in
    Sort
 
Андрей Лящук, спасибо!
Нужны! Для поиска! Я, правда, далеко не уверен, что смогу реализовать задуманное!

Не работает последний запрос!
Скриншот я загрузил!
Из скриншота видно, что нет предмета только в нескольких случаях. А я ожила увидеть, что если урока нет, то и в поле предмет будет "чисто". Урока ведь нет
Но сейчас я думаю, а действительно ли нужно видеть, что урока нет. Я планирую в будущем использовать таблицу, чтобы можно было видеть есть ли у учителя окна, чтобы ставить(или не ставить) на замену

artyrH, я сейчас сам попытаюсь сделать условным доп. столбцом! Если урок = 1, то определять как смена 1, иначе = 2.  
Изменено: extrafant - 06.01.2020 11:42:24
Страницы: 1
Наверх