Я всегда хотел настроить автоматизированный экспорт задач из MLO в Excel для более детального анализа, наложения задач на календарь и т. д. Excel 2016 дал эту возможность за счет новой функции Get&Transform (Power Query) - теперь можно импортировать XML-файлы и проводить над ними сложные операции для преобразования в таблицы.
Кратко как это работает: я запускаю bat-файл, который консольной командой делает экспорт XML из MLO-профиля. Потом в Excel при нажатии кнопки "Данные - Обновить все" происходит ряд операций над этим файлом (используется рекурсивная функция в Power Query для разворачивания дерева), и в итоге получается таблица со списком задач и их параметрами (срочность, важность, даты начала и окончания и т. д.). Также я добавил поля с родительской задачей и полным путем к данной задаче в дереве.
Прикладываю архив с примером XML-файла, выгруженного из MLO, Excel-файлом, где настроен скрипт для обновления, и bat-файлом для более быстрого экспорта файла из MLO. В bat-файле прописаны абсолютные пути - их надо обновить! Также абсолютный путь прописан в excel-файле в запросе "MLO_Tasks" - его тоже надо изменить.
Если нужны более подробные инструкции что куда вставить и поменять, чтобы работало (по опыту уровень экселя очень сильно отличается среди людей) - пишите, добавлю.
Функция MLO_NextLevel в Power Query, которая позволила рекурсивно распарсить иерархию
Код: Выделить всё
(TableToExpand as table) as table =>
let
#"Renamed Full Path to Old" = Table.RenameColumns(TableToExpand,{{"Full Path", "Full Path Old"}}),
#"Added Full Path Next" = Table.AddColumn(#"Renamed Full Path to Old", "Full Path", each [Full Path Old] & [#"Attribute:Caption"] & "\"),
#"Removed Old Full Path" = Table.RemoveColumns(#"Added Full Path Next",{"Full Path Old"}),
#"Removed Parent" = Table.RemoveColumns(#"Removed Old Full Path",{"Parent"}),
#"Added Parent" = Table.AddColumn(#"Removed Parent", "Parent", each [#"Attribute:Caption"]),
#"Removed Other Columns" = Table.SelectColumns(#"Added Parent",{"TaskNode", "Full Path", "Parent"}),
#"Expanded TaskNode" = Table.ExpandTableColumn(#"Removed Other Columns", "TaskNode", {"TaskNode", "HideInToDoThisTask", "NextReviewDate", "IsProject", "Flag", "Created", "Attribute:Caption", "HideInToDo", "CustomFormat", "LastReviewed", "ReviewRecurrenceType", "Places", "CompletionDateTime", "CompleteSubTasksInOrder", "DueDateTime", "Importance", "LeadTime", "Note", "Reminder", "ScheduleType", "Starred", "StartDateTime", "StarToggleDateTime", "Urgency", "Recurrence"}, {"TaskNode", "HideInToDoThisTask", "NextReviewDate", "IsProject", "Flag", "Created", "Attribute:Caption", "HideInToDo", "CustomFormat", "LastReviewed", "ReviewRecurrenceType", "Places", "CompletionDateTime", "CompleteSubTasksInOrder", "DueDateTime", "Importance", "LeadTime", "Note", "Reminder", "ScheduleType", "Starred", "StartDateTime", "StarToggleDateTime", "Urgency", "Recurrence"}),
#"Added Check Empty" = Table.AddColumn(#"Expanded TaskNode", "Check Empty", each Table.IsEmpty([TaskNode])),
#"Replaced Errors" = Table.ReplaceErrorValues(#"Added Check Empty", {{"Check Empty", true}}),
#"Filtered Empty" = Table.SelectRows(#"Replaced Errors", each [Check Empty] = false),
#"Count Rows" = Table.RowCount(#"Filtered Empty"),
#"Condition" = if #"Count Rows" = 0
then #"Expanded TaskNode"
else Table.Combine({#"Expanded TaskNode", MLO_NextLevel(#"Expanded TaskNode")})
in
#"Condition"
Запрос MLO_Tasks в Power Query, который берет на вход XML, вызывает MLO_NextLevel и дотачивает результат
Код: Выделить всё
let
Source = Xml.Tables(File.Contents("C:\MLO\mlo_xml.xml")),
#"Removed Other Columns" = Table.SelectColumns(Source,{"TaskTree"}),
#"Expanded TaskTree" = Table.ExpandTableColumn(#"Removed Other Columns", "TaskTree", {"TaskNode"}, {"TaskNode"}),
#"Added Parent" = Table.AddColumn(#"Expanded TaskTree", "Parent", each ""),
#"Added Full Path" = Table.AddColumn(#"Added Parent", "Full Path", each ""),
#"Expanded TaskNode" = Table.ExpandTableColumn(#"Added Full Path", "TaskNode", {"Attribute:Caption", "Created", "TaskNode"}, {"Attribute:Caption", "Created", "TaskNode"}),
#"Expand All" = MLO_NextLevel(#"Expanded TaskNode"),
#"Filtered Rows" = Table.SelectRows(#"Expand All", each ([#"Attribute:Caption"] <> null)),
#"Replaced Value" = Table.ReplaceValue(#"Filtered Rows","T"," ",Replacer.ReplaceText,{"NextReviewDate", "Created", "LastReviewed", "CompletionDateTime", "StartDateTime", "StarToggleDateTime"}),
#"Removed Columns" = Table.RemoveColumns(#"Replaced Value",{"TaskNode"}),
#"Reordered Columns" = Table.ReorderColumns(#"Removed Columns",{"Attribute:Caption", "Full Path", "Parent", "CompletionDateTime", "HideInToDoThisTask", "NextReviewDate", "IsProject", "Flag", "Created", "HideInToDo", "CustomFormat", "LastReviewed", "ReviewRecurrenceType", "Places", "CompleteSubTasksInOrder", "DueDateTime", "Importance", "LeadTime", "Note", "Reminder", "ScheduleType", "Starred", "StartDateTime", "StarToggleDateTime", "Urgency"}),
#"Renamed Columns" = Table.RenameColumns(#"Reordered Columns",{{"Attribute:Caption", "Caption"}}),
#"Expanded Places" = Table.ExpandTableColumn(#"Renamed Columns", "Places", {"Place"}, {"Places"}),
#"Added Context" = Table.AddColumn(#"Expanded Places", "Context", each Text.Combine(Table.ToList([Places]), ", ")),
#"Replaced Errors in Context" = Table.ReplaceErrorValues(#"Added Context", {{"Context", null}}),
#"Finalized Context" = Table.ReplaceValue(#"Replaced Errors in Context",null,each [Places],Replacer.ReplaceValue,{"Context"}),
#"Removed Places" = Table.RemoveColumns(#"Finalized Context",{"Places"}),
#"Added Notes" = Table.AddColumn(#"Removed Places", "Notes", each if Table.IsEmpty([Note]) then "" else Record.Field([Note]{0},"Element:Text")),
#"Replaced Errors in Notes" = Table.ReplaceErrorValues(#"Added Notes", {{"Notes", null}}),
#"Finalized Notes" = Table.ReplaceValue(#"Replaced Errors in Notes",null,each [Note],Replacer.ReplaceValue,{"Notes"}),
#"Changed Type" = Table.TransformColumnTypes(#"Finalized Notes",{{"StarToggleDateTime", type datetime}, {"StartDateTime", type datetime}, {"DueDateTime", type datetime}, {"CompletionDateTime", type datetime}, {"Created", type datetime}, {"LastReviewed", type datetime}, {"NextReviewDate", type datetime}, {"HideInToDoThisTask", Int64.Type}, {"IsProject", Int64.Type}, {"HideInToDo", Int64.Type}, {"ReviewRecurrenceType", Int64.Type}, {"CompleteSubTasksInOrder", Int64.Type}, {"Importance", Int64.Type}, {"ScheduleType", Int64.Type}, {"Starred", Int64.Type}, {"Urgency", Int64.Type}, {"Parent", type text}, {"Full Path", type text}, {"Notes", type text}, {"Caption", type text}, {"Flag", type text}, {"Context", type text}}),
#"Reordered Columns1" = Table.ReorderColumns(#"Changed Type",{"Caption", "Full Path", "Parent", "CompletionDateTime", "StartDateTime", "DueDateTime", "HideInToDoThisTask", "NextReviewDate", "IsProject", "Flag", "Created", "HideInToDo", "CustomFormat", "LastReviewed", "ReviewRecurrenceType", "CompleteSubTasksInOrder", "Importance", "LeadTime", "Note", "Reminder", "ScheduleType", "Starred", "StarToggleDateTime", "Urgency", "Context"}),
#"Removed Columns1" = Table.RemoveColumns(#"Reordered Columns1",{"Note"})
in
#"Removed Columns1"