Список всех импортированных САПР файлов
Вы когда-нибудь беспокоились о том, есть ли у вас дубликаты импортов из САПР форматов?
Мой коллега Николай Шульга (Nikolay Shulga) из команды разработчиков Revit реализовал маленькую полезную утилиту для ответа на этот вопрос.
Вот что он пишет:
Когда-то я написал прототип приложения для вывода всех импортированных объектов в проект Revit. Идея состояла в том, чтобы вывести дублирующийся экземпляры. Люди часто импортируют одни и те же данные несколько раз.
Я не думаю, что я смогу до конца доработать это приложение. Может быть опубликовав этот прототип на своем блоге, и кто-нибудь подхватит эту идею. Или еще лучше – сделать это приложение open-source.
- Мотивация – Люди часто импортируют чертежи. Обычно DWG. При этом несколько раз один и тот же чертеж на разные виды. Из-за этого размер документа увеличивается и снижается производительность. Мы обнаружили, что люде не часто знают, что за данные они импортируют.
- Спецификация – Вывести список импортированных данных и вывести их в полезном для анализа виде.
- Реализация – смотрите ниже
- Как это можно улучшить – одной из идеей была возможность создания диспетчера импортированных файлов, подобно тому, как отображается список видов.
- Подходящая модель для тестирования – любой проект с импортированным несколько раз одним и тем же DWG файлом.
Вот текущая реализация.
- #region Namespaces
- using System;
- using System.Collections.Generic;
- using System.Collections.Specialized;
- using System.Diagnostics;
- using Autodesk.Revit.ApplicationServices;
- using Autodesk.Revit.Attributes;
- using Autodesk.Revit.DB;
- using Autodesk.Revit.UI;
- using Autodesk.Revit.UI.Selection;
- using System.IO;
- #endregion
- namespace ListImportInstances
- {
- /// <summary>
- /// Интерфейс для генерации отчета по имортированным файлам
- /// в конкретном проекте
- /// </summary>
- interface IReportImportData
- {
- bool init(string projectName);
- void startReportSection(string sectionName);
- void logItem(string item);
- void setWarning();
- void done();
- string getLogFileName();
- }
- class SimpleTextFileBasedReporter : IReportImportData
- {
- public SimpleTextFileBasedReporter()
- {
- }
- public bool init(string projectFileName)
- {
- bool outcome = false;
- m_currentSection = null;
- m_warnUser = false;
- if (0 != projectFileName.Length)
- {
- m_projectFileName = projectFileName;
- }
- else
- {
- m_projectFileName = "Default";
- }
- m_logFileName = System.IO.Path.Combine(
- System.IO.Path.GetDirectoryName(m_projectFileName),
- System.IO.Path.GetFileNameWithoutExtension(
- m_projectFileName)) + "-ListOfImportedData.txt";
- // Construct log file name from projectFileName
- // and try to open file. Project file name is
- // assumed to be valid (expected to be called
- // on an open doc).
- // Создаем название лог файла исходя из названия проекта и
- // пробуем открыть файл.
- // Предполагаем, что имя файла проекта валидное
- try
- {
- m_outputFile = new StreamWriter(m_logFileName);
- m_outputFile.WriteLine("Список импортированных САПР файлов"
- + projectFileName);
- outcome = true;
- }
- catch (System.UnauthorizedAccessException)
- {
- TaskDialog.Show("FindImports",
- "You are not authorized to create "
- + m_logFileName);
- }
- catch (System.ArgumentNullException) // oh, come on.
- {
- TaskDialog.Show("FindImports",
- "Так не честно. Null argument for StreamWriter()");
- }
- catch (System.ArgumentException)
- {
- TaskDialog.Show("FindImports",
- "Не удалось создать " + m_logFileName);
- }
- catch (System.IO.DirectoryNotFoundException)
- {
- TaskDialog.Show("FindImports",
- "Такого не должно было случиться. ДИректория не найдена: "
- + System.IO.Path.GetDirectoryName(m_projectFileName));
- }
- catch (System.IO.PathTooLongException)
- {
- TaskDialog.Show("FindImports",
- "КАжеется название файла " + m_logFileName
- + " Слишком длинное");
- }
- catch (System.IO.IOException)
- {
- TaskDialog.Show("FindImports",
- "Ошибка ввода вывода в файле "
- + m_logFileName);
- }
- catch (System.Security.SecurityException)
- {
- TaskDialog.Show("FindImports",
- "Нет прав доступа для записи файла "
- + System.IO.Path.GetDirectoryName(m_projectFileName)
- + "");
- }
- return outcome;
- }
- public void startReportSection(string sectionName)
- {
- endReportSection();
- m_outputFile.WriteLine();
- m_outputFile.WriteLine(sectionName);
- m_outputFile.WriteLine();
- m_currentSection = sectionName;
- }
- public void logItem(string item)
- {
- m_outputFile.WriteLine(item);
- }
- public void setWarning()
- {
- m_warnUser = true;
- }
- public void done()
- {
- endReportSection();
- m_outputFile.WriteLine();
- m_outputFile.WriteLine("The End");
- m_outputFile.WriteLine();
- m_outputFile.Close();
- // Display "done" dialog, potentially open log file
- // Диалог завершения и открытия лог-файла
- TaskDialog doneMsg = null;
- if (m_warnUser)
- {
- doneMsg = new TaskDialog(
- "Найдены возможные проблемы. Смотрите лог файл");
- }
- else
- {
- doneMsg = new TaskDialog(
- "Поиск импортированных САПР файлов завершен");
- }
- doneMsg.AddCommandLink(
- TaskDialogCommandLinkId.CommandLink1,
- "Просмотр файла " + m_logFileName);
- switch (doneMsg.Show())
- {
- default:
- break;
- case TaskDialogResult.CommandLink1:
- // Display the log file
- Process.Start("notepad.exe", m_logFileName);
- break;
- }
- }
- public string getLogFileName()
- {
- return m_logFileName;
- }
- private void endReportSection()
- {
- if (null != m_currentSection)
- {
- m_outputFile.WriteLine();
- m_outputFile.WriteLine("Конец "
- + m_currentSection);
- m_outputFile.WriteLine();
- }
- }
- private string m_projectFileName;
- private string m_logFileName;
- private StreamWriter m_outputFile;
- private string m_currentSection;
- /// <summary>
- /// говорим пользователю что нужно просмотреть лог
- /// </summary>
- private bool m_warnUser;
- }
- [Transaction(TransactionMode.ReadOnly)]
- public class Command : IExternalCommand
- {
- private void listImports(Document doc)
- {
- FilteredElementCollector col
- = new FilteredElementCollector(doc)
- .OfClass(typeof(ImportInstance));
- NameValueCollection listOfViewSpecificImports
- = new NameValueCollection();
- NameValueCollection listOfModelImports
- = new NameValueCollection();
- NameValueCollection listOfUnidentifiedImports
- = new NameValueCollection();
- foreach (Element e in col)
- {
- // Collect all view-specific names.
- // собираем все видоориентированные имена
- if (e.ViewSpecific)
- {
- string viewName = null;
- try
- {
- Element viewElement = doc.GetElement(
- e.OwnerViewId);
- viewName = viewElement.Name;
- }
- catch (Autodesk.Revit.Exceptions
- .ArgumentNullException) // на всякий случай проверим
- {
- viewName = String.Concat(
- "Invalid View ID: ",
- e.OwnerViewId.ToString());
- }
- if (null != e.Category)
- {
- listOfViewSpecificImports.Add(
- importCategoryNameToFileName(
- e.Category.Name), viewName);
- }
- else
- {
- listOfUnidentifiedImports.Add(
- e.Id.ToString(), viewName);
- }
- }
- else
- {
- listOfModelImports.Add(
- importCategoryNameToFileName(
- e.Category.Name), e.Name);
- }
- }
- IReportImportData logOutput
- = new SimpleTextFileBasedReporter();
- if (!logOutput.init(doc.PathName))
- {
- TaskDialog.Show("FindImports",
- "Не удалось создать файла отчета");
- }
- else
- {
- if (listOfViewSpecificImports.HasKeys())
- {
- logOutput.startReportSection(
- "Видоориентированные САПР файлы");
- listResults(listOfViewSpecificImports,
- logOutput);
- }
- if (listOfModelImports.HasKeys())
- {
- logOutput.startReportSection("Импортированные модели");
- listResults(listOfModelImports, logOutput);
- }
- if (listOfUnidentifiedImports.HasKeys())
- {
- logOutput.startReportSection(
- "Неизвестные импортированные файлы");
- listResults(listOfUnidentifiedImports,
- logOutput);
- }
- if (!sanityCheckViewSpecific(
- listOfViewSpecificImports, logOutput))
- {
- logOutput.setWarning();
- //TaskDialog.Show("FindImportedData",
- //"Possible issues found. Please review the log file");
- }
- logOutput.done();
- }
- }
- /// <summary>
- /// Импортированные категории. Они создаются из имени
- /// САПР файла + соответствующий индексю
- /// Мы хотим использовать имя файла в качестве
- /// первичного ключа в нашем списке импортированных файловю
- /// </summary>
- private string importCategoryNameToFileName(
- string catName)
- {
- string fileName = catName;
- fileName = fileName.Trim();
- if (fileName.EndsWith(")"))
- {
- int lastLeftBracket = fileName.LastIndexOf("(");
- if (-1 != lastLeftBracket)
- fileName = fileName.Remove(lastLeftBracket); // Удаляем левую скобку
- }
- return fileName.Trim();
- }
- private void listResults(
- NameValueCollection listOfImports,
- IReportImportData logFile)
- {
- foreach (String key in listOfImports.AllKeys)
- {
- logFile.logItem(key + ": "
- + listOfImports.Get(key));
- }
- }
- /// <summary>
- /// Запускаем проверку списка видоориентированных импортов.
- /// Видориентированная проверка это не то же самое
- /// что и проверка по все модели.
- /// </summary>
- private bool sanityCheckViewSpecific(
- NameValueCollection listOfImports,
- IReportImportData logFile)
- {
- logFile.startReportSection(
- "Проверка на видоориентированные импорты");
- bool status = true;
- //Считаем количество
- foreach (String key in listOfImports.AllKeys)
- {
- string[] levels = listOfImports.GetValues(key);
- if (levels != null && levels.GetLength(0) > 1)
- {
- logFile.logItem("САПР файл " + key
- + " были импортированы в "
- + "в режиме Ориентировать по виду несколько раз. "
- + "Он находится в следующих видах "
- + listOfImports.Get(key));
- status = false;
- }
- }
- return status;
- }
- public Result Execute(
- ExternalCommandData commandData,
- ref string message,
- ElementSet elements)
- {
- UIApplication uiapp = commandData.Application;
- UIDocument uidoc = uiapp.ActiveUIDocument;
- Document doc = uidoc.Document;
- listImports(doc);
- return Result.Succeeded;
- }
- }
- }
Спасибо Николаю за реализацию. Я последовал инструкции Николая и создал небольшой проект и импортировал три раза один DWG файл.
Запустив команду, будет сгенерирован отчет в текстовый файл.
Как обычно, самую последнюю версию можно найти на GitHub.
Жду от вас предложений как можно улучшить приложение.
Не стесняйтесь делать форки и пул-реквесты.
Источник: http://thebuildingcoder.typepad.com/blog/2015/04/list-all-import-instances.html
Обсуждение: http://adn-cis.org/forum/index.php?topic=2731
Опубликовано 22.05.2015