ADN Open CIS
Сообщество программистов Autodesk в СНГ

14/04/2014

Добавление материалов из списка

Еще в далеком 2011 году мы обсуждали как импортировать материалы из файла Excel в Revit.

Входные данные хранились в файле Excel и содержали следующие параметры:

Наименование

  • Код
  • Название
  • Сила

Графика

  • Цвет в RGB
  • Прозрачность
  • Штриховка разреза
  • Штриховка поверхности

Идентификация

  • Класс
  • Информация о продукте
  • Пользовательские параметры

У пользователя была проблема, что он не мог добраться программно создать материал с заданным классом.

В итоге поступили следующим образом:

  1. Создали в интерфейсе Revit список предопределенных материалов с нужным классом, где название материала совпадало с названием класса
  2. При импорте искали материал с нужным названием и копировали его. Тем самым и создавали новый материал с нужным классом

Надстройка была реализована для Revit 2011 и Revit API уже изменилось с тех пор и поэтому надстройка немного изменилась.

Вот список методов, которые необходимо изменить для Revit API 2014.

  1. Использовать FilteredElementCollector для доступа к материалам и штриховкам и LINQ для создания словаря соответствия имени материала с самим объектом материалом.
  2. Цвет необходимо задавать в конструкторе класса Color.
  3. Установить штриховку поверхности материала и разреза с помощью ElementId.

Так же я немного почистил и оптимизировал код.

Помимо этого, я внес изменения в вывод итогового сообщения, добавив информацию о том, сколько материалов было фактически добавлено.

Первоначальная реализация обновления имела баг с обработкой штриховки. Так как файл Excel для некоторых позиций содержит значение N/A, то естественно, что штриховки с таким именем нет и поэтому выдавалась ошибка.

Я подправил код и добавил проверку на значение N/A:

Код - C#: [Выделить]
  1.   const string _not_available = "N/A";
  2.  
  3.   if( 0 < surPattern.Length
  4.     && !surPattern.Equals( _not_available ) )
  5.   {
  6.     myMaterial.SurfacePatternId
  7.       = fillPatterns[surPattern].Id;
  8.   }
  9.  
  10.   if( 0 < cutPattern.Length
  11.     && !cutPattern.Equals( _not_available ) )
  12.   {
  13.     myMaterial.CutPatternId
  14.       = fillPatterns[cutPattern].Id;
  15.   }

Однако все же осталась не решенная проблема: если количество добавленных материалов меньше, чем количество обработанных строк, то по какой-то причине не все материалы были добавлены. Пользователь же так и не узнает причину.

Так что имейте ввиду, что возможно вам придется доработать код, если потребуется.

Я все же решил внести небольшое изменение и добавил название материалов, которые были добавлены, вместо простого отображения количества.

В результате я могу получить вот такой отчет:

 

Конечно, пользователь все еще не знает в этом случае причину не добавления материала, но то что выводится список добавленных материалов – уже не плохо.

И, в завершение, полный код команды:

Код - C#: [Выделить]
  1.   [Transaction( TransactionMode.Manual )]
  2.   public class Command : IExternalCommand
  3.   {
  4.     const string _not_available = "N/A";
  5.  
  6.     const string _input_file_name = "C:/RevitAPI/MaterialList.xlsx";
  7.  
  8.     static string PluralSuffix( int i )
  9.     {
  10.       return 1 == i ? "" : "s";
  11.     }
  12.  
  13.     public Result Execute(
  14.       ExternalCommandData commandData,
  15.       ref string message,
  16.       ElementSet elements )
  17.     {
  18.       UIApplication uiapp = commandData.Application;
  19.       UIDocument uidoc = uiapp.ActiveUIDocument;
  20.       Document doc = uidoc.Document;
  21.  
  22.       // Создаем слоарь с сопоставлением названия материлов, объекту материала
  23.  
  24.       Dictionary<string, Material> materials
  25.         = new FilteredElementCollector( doc )
  26.           .OfClass( typeof( Material ) )
  27.           .Cast<Material>()
  28.           .ToDictionary<Material, string>(
  29.             e => e.Name );
  30.  
  31.       // То же и для штирховок.
  32.  
  33.       Dictionary<string, FillPatternElement> fillPatterns
  34.         = new FilteredElementCollector( doc )
  35.           .OfClass( typeof( FillPatternElement ) )
  36.           .Cast<FillPatternElement>()
  37.           .ToDictionary<FillPatternElement, string>(
  38.             e => e.Name );
  39.  
  40.       try
  41.       {
  42.         Excel.Application excel
  43.           = new Excel.Application();
  44.  
  45.         excel.Visible = false;
  46.  
  47.         Excel.Workbook workbook = excel.Workbooks.Open(
  48.           _input_file_name, 0, true, 5, "", "", true,
  49.           Excel.XlPlatform.xlWindows, "\t", false,
  50.           false, 0, true, 1, 0 );
  51.  
  52.         Excel.Worksheet worksheet = (Excel.Worksheet)
  53.           workbook.Worksheets.get_Item( 1 );
  54.  
  55.         Excel.Range range = worksheet.UsedRange;
  56.  
  57.         int nRows = 0;
  58.         List<string> materials_added = new List<string>();
  59.  
  60.         int iRow = 5;
  61.  
  62.         using( Transaction tx = new Transaction( doc ) )
  63.         {
  64.           tx.Start( "Добавление материала" );
  65.  
  66.           while( null != range.Cells[iRow, 1].Value2 )
  67.           {
  68.             string matName = (string) range.Cells[iRow, 1].Value2;
  69.             matName += " " + (string) range.Cells[iRow, 2].Value2;
  70.             matName += " " + (string) range.Cells[iRow, 3].Value2;
  71.  
  72.             if( matName != null )
  73.             {
  74.               double red = (double) range.Cells[iRow, 4].Value2;
  75.               double green = (double) range.Cells[iRow, 5].Value2;
  76.               double blue = (double) range.Cells[iRow, 6].Value2;
  77.               double transparency = (double) range.Cells[iRow, 8].Value2;
  78.               string surPattern = (string) range.Cells[iRow, 9].Value2;
  79.               string cutPattern = (string) range.Cells[iRow, 10].Value2;
  80.  
  81.               // Ищем материал для копирования
  82.  
  83.               string CSI = (string) range.Cells[iRow, 11].Value2;
  84.  
  85.               if( materials.ContainsKey( CSI ) )
  86.               {
  87.                 Material materialCSI = materials[CSI];
  88.  
  89.                 Material myMaterial
  90.                   = materialCSI.Duplicate( matName );
  91.  
  92.                 Color matColor = new Color(
  93.                   Byte.Parse( red.ToString() ),
  94.                   Byte.Parse( green.ToString() ),
  95.                   Byte.Parse( blue.ToString() ) );
  96.  
  97.                 myMaterial.Color = matColor;
  98.  
  99.                 myMaterial.Transparency
  100.                   = (int) transparency;
  101.  
  102.                 if( 0 < surPattern.Length
  103.                   && !surPattern.Equals( _not_available ) )
  104.                 {
  105.                   myMaterial.SurfacePatternId
  106.                     = fillPatterns[surPattern].Id;
  107.                 }
  108.  
  109.                 if( 0 < cutPattern.Length
  110.                   && !cutPattern.Equals( _not_available ) )
  111.                 {
  112.                   myMaterial.CutPatternId
  113.                     = fillPatterns[cutPattern].Id;
  114.                 }
  115.                 materials_added.Add( matName );
  116.               }
  117.             }
  118.             ++nRows;
  119.             ++iRow;
  120.           }
  121.           tx.Commit();
  122.         }
  123.  
  124.         workbook.Close( true, null, null );
  125.         excel.Quit();
  126.  
  127.         int n = materials_added.Count;
  128.  
  129.         string msg = string.Format(
  130.           "{0} строк обработано "
  131.           + "{1} материалов добавлено:",
  132.           nRows, n  );
  133.  
  134.         TaskDialog dlg = new TaskDialog(
  135.           "Добавление материалов" );
  136.        
  137.         dlg.MainInstruction = msg;
  138.  
  139.         dlg.MainContent = string.Join( ", ",
  140.           materials_added ) + ".";
  141.  
  142.         dlg.Show();
  143.  
  144.         return Result.Succeeded;
  145.       }
  146.       catch( Exception ex )
  147.       {
  148.         message = "Revit AddMaterials Exception:\n"
  149.           + ex.ToString();
  150.  
  151.         return Result.Failed;
  152.       }
  153.     }
  154.   }

Код с проектом для Visual Studio доступен на GitHub.

Источник: http://thebuildingcoder.typepad.com/blog/2010/08/add-new-materials-from-list.html#2
http://thebuildingcoder.typepad.com/blog/2014/03/adding-new-materials-from-list-updated.html
http://thebuildingcoder.typepad.com/blog/2014/03/adding-new-materials-from-list-updated-again.html

Обсуждение: http://adn-cis.org/forum/index.php?topic=678

Опубликовано 14.04.2014