Example #1
0
        private int getRowColumnCount(ViewSchedule view, SectionType sectionType, bool countRows)
        {
            int ctr = 1;

            // loop over the columns of the schedule
            while (true)
            {
                try                 // GetCellText will throw an ArgumentException is the cell does not exist
                {
                    if (countRows)
                    {
                        view.GetCellText(sectionType, ctr, 1);
                    }
                    else
                    {
                        view.GetCellText(sectionType, 1, ctr);
                    }
                    ctr++;
                }
                catch (Autodesk.Revit.Exceptions.ArgumentException)
                {
                    return(ctr);
                }
            }
        }
        public string GetScheduleUnit(ViewSchedule schedule)
        {
            TableData        table   = schedule.GetTableData();
            TableSectionData section = table.GetSectionData(SectionType.Body);

            if (section.NumberOfRows > 0)
            {
                for (int col = section.NumberOfColumns - 1; col >= 0; col--)
                {
                    string unit = schedule.GetCellText(SectionType.Body, section.NumberOfRows - 1, col);
                    if (unit.Length > 0)
                    {
                        if (unit.Contains(" "))
                        {
                            return(unit.Remove(0, unit.IndexOf(" ") + 1));
                        }
                        else
                        {
                            return("kg");
                        }
                    }
                }
            }
            return("");
        }
        public double GetScheduleQuantity(ViewSchedule schedule)
        {
            TableData        table   = schedule.GetTableData();
            TableSectionData section = table.GetSectionData(SectionType.Body);

            if (section.NumberOfRows > 0)
            {
                for (int col = section.NumberOfColumns - 1; col >= 0; col--)
                {
                    string strValue = schedule.GetCellText(SectionType.Body, section.NumberOfRows - 1, col);
                    if (strValue.Length > 0)
                    {
                        if (strValue.Contains(" "))
                        {
                            strValue = strValue.Remove(strValue.IndexOf(" "));
                            if (double.TryParse(strValue, out double value))
                            {
                                return(value);
                            }
                        }
                        else if (double.TryParse(strValue, out double value))
                        {
                            return(value);
                        }
                    }
                }
            }
            return(0.0);
        }
Example #4
0
        /// <summary>
        /// Заполнение листа моделей значением параметров
        /// </summary>
        /// <param name="rowModelList"></param>
        private void FillListModelParameters(List <RowModel> rowModelList)
        {
            foreach (var parameter in _parametersList)
            {
                OpenColumnByName(parameter);
                for (int j = 4; j < _tsd.NumberOfRows; j++)
                {
                    if (parameter == "КМ.ГруппаКонструкций" || parameter == "Арм.НомерПодтипаФормы")
                    {
                        var el = rowModelList.Where(i => i.NumberOfRow == j).ToList().First();
                        if (parameter == "КМ.ГруппаКонструкций")
                        {
                            el.ArmNumberOfForm = _tsd.GetCellText(j, _tsd.LastColumnNumber);
                        }
                        else if (parameter == "Арм.НомерПодтипаФормы")
                        {
                            if (_tsd.GetCellText(j, _tsd.LastColumnNumber) == string.Empty)
                            {
                                el.ArmNumberOfUnderForm = "0";
                            }
                            else
                            {
                                el.ArmNumberOfUnderForm = _tsd.GetCellText(j, _tsd.LastColumnNumber);
                            }
                        }
                    }
                    else
                    {
                        var el = rowModelList.Where(i => i.NumberOfRow == j).ToList().First();

                        var test = _viewSchedule.GetCellText(SectionType.Body, j, _tsd.LastColumnNumber);
                        if (_viewSchedule.GetCellText(SectionType.Body, j, _tsd.LastColumnNumber) != string.Empty)
                        {
                            var newCell = new ScheduleFieldModel()
                            {
                                FieldName     = parameter,
                                ValueAsString = _viewSchedule.GetCellText(SectionType.Body, j, _tsd.LastColumnNumber)
                            };
                            el.SheduleFieldList.Add(newCell);
                        }
                    }
                }
                CloseColumnByName(parameter);
            }
        }
        //public QLViewScheduleResolve(ViewSchedule aViewSchedule, Field queryFieldForViewScheduleData)
        //{
        //    id = aViewSchedule.Id.ToString();
        //    name = aViewSchedule.Name;

        //    if (queryFieldForViewScheduleData != null)
        //    {
        //        try
        //        {
        //            qlViewScheduleData = ResolverEntry.aRevitTask.Run<QLViewScheduleData>(app =>
        //            {
        //                ////https://thebuildingcoder.typepad.com/blog/2012/05/the-schedule-api-and-access-to-schedule-data.html
        //                TableData table = aViewSchedule.GetTableData();
        //                var rowCount = aViewSchedule.GetTableData().GetSectionData(SectionType.Body).NumberOfRows;
        //                var colCount = aViewSchedule.GetTableData().GetSectionData(SectionType.Body).NumberOfColumns;

        //                QLViewScheduleData data = new QLViewScheduleData();
        //                data.headers = new List<string>();
        //                data.rows = new List<QLViewScheduleRow>();

        //                for (int i = 0; i < rowCount; i++)
        //                {
        //                    QLViewScheduleRow newRow = new QLViewScheduleRow();
        //                    newRow.id = i.ToString();
        //                    newRow.cells = new List<string>();
        //                    for (int j = 0; j < colCount; j++)
        //                    {
        //                        var cellString = aViewSchedule.GetCellText(SectionType.Body, i, j);
        //                        if (i == 0)
        //                        {
        //                            data.headers.Add(cellString);
        //                        }
        //                        else
        //                        {
        //                            newRow.cells.Add(cellString);
        //                        }
        //                    }
        //                    if (i == 0)
        //                    {
        //                        i++; // skip 2nd row - it's always blank
        //                    }
        //                    else
        //                    {
        //                        data.rows.Add(newRow);
        //                    }
        //                }
        //                return data;
        //            }).Result;
        //        }
        //        catch (Exception ex)
        //        {
        //            var m = ex.Message;
        //        }
        //    }
        //}
        public QLViewScheduleResolve(ViewSchedule aViewSchedule, object aFieldOrContext)
        {
            id   = aViewSchedule.Id.ToString();
            name = aViewSchedule.Name;

            var queryFieldForViewScheduleData = GraphQlHelpers.GetFieldFromFieldOrContext(aFieldOrContext, "qlViewScheduleData");

            if (queryFieldForViewScheduleData != null)
            {
                try
                {
                    qlViewScheduleData = ResolverEntry.aRevitTask.Run <QLViewScheduleData>(app =>
                    {
                        ////https://thebuildingcoder.typepad.com/blog/2012/05/the-schedule-api-and-access-to-schedule-data.html
                        TableData table = aViewSchedule.GetTableData();
                        var rowCount    = aViewSchedule.GetTableData().GetSectionData(SectionType.Body).NumberOfRows;
                        var colCount    = aViewSchedule.GetTableData().GetSectionData(SectionType.Body).NumberOfColumns;

                        QLViewScheduleData data = new QLViewScheduleData();
                        data.headers            = new List <string>();
                        data.rows = new List <QLViewScheduleRow>();

                        for (int i = 0; i < rowCount; i++)
                        {
                            QLViewScheduleRow newRow = new QLViewScheduleRow();
                            newRow.id    = i.ToString();
                            newRow.cells = new List <string>();
                            for (int j = 0; j < colCount; j++)
                            {
                                var cellString = aViewSchedule.GetCellText(SectionType.Body, i, j);
                                if (i == 0)
                                {
                                    data.headers.Add(cellString);
                                }
                                else
                                {
                                    newRow.cells.Add(cellString);
                                }
                            }
                            if (i == 0)
                            {
                                i++; // skip 2nd row - it's always blank
                            }
                            else
                            {
                                data.rows.Add(newRow);
                            }
                        }
                        return(data);
                    }).Result;
                }
                catch (Exception ex)
                {
                    var m = ex.Message;
                }
            }
        }
Example #6
0
        /// <summary>
        ///     Converts revit detail view to a DataTable.
        /// </summary>
        /// <param name="view"></param>
        /// <param name="doc"></param>
        /// <returns></returns>
        public static DataTable ToDataTable(this ViewSchedule view, Document doc)
        {
            if (view is null)
            {
                throw new ArgumentNullException(nameof(view));
            }

            if (doc is null)
            {
                throw new ArgumentNullException(nameof(doc));
            }

            var table = view.GetTableData();

            var body = table.GetSectionData(SectionType.Body);

            var colNum = body.NumberOfColumns;

            var rowNum = body.NumberOfRows;

            var result = new DataTable {
                TableName = view.GetCellText(SectionType.Header, 0, 0)
            };

            for (var i = 0; i < colNum; i++)
            {
                result.Columns.Add();
            }

            for (var i = 0; i < rowNum; i++)
            {
                var row = result.NewRow();

                for (var j = 0; j < colNum; j++)
                {
                    row[j] = view.GetCellText(SectionType.Body, i, j);
                }

                result.Rows.Add(row);
            }

            return(result);
        }
Example #7
0
        public void Schedule2014GetCellText()
        {
            UIDocument   uidoc        = this.ActiveUIDocument;
            Document     doc          = uidoc.Document;
            ViewSchedule viewSchedule = doc.ActiveView as ViewSchedule;
            SectionType  sectionType  = SectionType.Body;

            string data = "";

            for (int i = 0; i < getRowColumnCount(viewSchedule, sectionType, true); i++)
            {
                for (int j = 0; j < getRowColumnCount(viewSchedule, sectionType, false); j++)
                {
                    data += viewSchedule.GetCellText(sectionType, i, j) + ",";
                }
                // remove the trailing "," after the last cell and add a newline for the end of this row
                data = data.TrimEnd(',') + "\n";
            }
            TaskDialog.Show(viewSchedule.Name, data);
        }
Example #8
0
        /// <summary>
        /// The getScheduleData
        /// </summary>
        /// <param name="doc">The doc<see cref="Document"/></param>
        public void getScheduleData(Document doc)
        {
            FilteredElementCollector collector  = new FilteredElementCollector(doc);
            IList <Element>          collection = collector.OfClass(typeof(ViewSchedule)).ToElements();

            String prompt = "ScheduleData :";

            prompt += Environment.NewLine;

            foreach (Element e in collection)
            {
                ViewSchedule     viewSchedule = e as ViewSchedule;
                TableData        table        = viewSchedule.GetTableData();
                TableSectionData section      = table.GetSectionData(SectionType.Body);
                int nRows    = section.NumberOfRows;
                int nColumns = section.NumberOfColumns;

                if (nRows > 1)
                {
                    //valueData.Add(viewSchedule.Name);

                    List <List <string> > scheduleData = new List <List <string> >();
                    for (int i = 0; i < nRows; i++)
                    {
                        List <string> rowData = new List <string>();

                        for (int j = 0; j < nColumns; j++)
                        {
                            rowData.Add(viewSchedule.GetCellText(SectionType.Body, i, j));
                        }
                        scheduleData.Add(rowData);
                    }

                    List <string> columnData = scheduleData[0];
                    scheduleData.RemoveAt(0);

                    DataMapping(columnData, scheduleData);
                }
            }
        }
Example #9
0
        private Dictionary <string, FamilyInstance> Sortdic(Dictionary <string, FamilyInstance> dic, ViewSchedule viewSchedule)
        {
            Dictionary <string, FamilyInstance> dic2 = new Dictionary <string, FamilyInstance>();
            var              keys            = dic.Keys.ToList();
            List <string>    listtexts       = new List <string>();
            List <string>    Newtexts        = new List <string>();
            TableData        tableData       = viewSchedule.GetTableData();
            TableSectionData sectionData     = tableData.GetSectionData(SectionType.Body);
            int              numberOfRows    = sectionData.NumberOfRows;
            int              numberOfColumns = sectionData.NumberOfColumns;

            //for (int i = 0; i < numberOfRows; i++)
            //{
            //	for (int j = 0; j < numberOfColumns; j++)
            //	{
            //		string cellText = viewSchedule.GetCellText(SectionType.Body, i, j);
            //		listtexts.Add(cellText);
            //	}
            //}
            for (int i = 0; i < numberOfRows; i++)
            {
                string cellText = viewSchedule.GetCellText(SectionType.Body, i, 0);
                listtexts.Add(cellText);
            }
            foreach (var item in listtexts)
            {
                foreach (var item2 in keys)
                {
                    if (item.Equals(item2))
                    {
                        Newtexts.Add(item);
                    }
                }
            }
            foreach (var item in Newtexts)
            {
                dic2.Add(item, dic[item]);
            }
            return(dic2);
        }
Example #10
0
        public List <List <string> > getScheduleData(Document doc, ViewSchedule viewSchedule)
        {
            TableData        table   = viewSchedule.GetTableData();
            TableSectionData section = table.GetSectionData(SectionType.Body);
            int nRows    = section.NumberOfRows;
            int nColumns = section.NumberOfColumns;

            List <List <string> > scheduleData = new List <List <string> >();

            if (viewSchedule.IsTitleblockRevisionSchedule)
            {
                scheduleData.Add(new List <string>()
                {
                    "HISTÓRICO DE REVISÕES"
                });
            }
            else
            {
                scheduleData.Add(new List <string>()
                {
                    viewSchedule.Name
                });
            }

            for (int i = 0; i < nRows; i++)
            {
                List <string> rowData = new List <string>();

                for (int j = 0; j < nColumns; j++)
                {
                    rowData.Add(viewSchedule.GetCellText(SectionType.Body, i, j));
                }
                scheduleData.Add(rowData);
            }
            return(scheduleData);
        }
        /// <summary>
        /// Получение сортированных элементов из спецификации с не установленной галочкой "Для каждого экземпляра"
        /// </summary>
        /// <param name="viewSchedule">Вид спецификации</param>
        /// <param name="elements">Элементы, полученные с этого вида</param>
        private IEnumerable <RowData <int> > GetSortedElementsFromNotItemizedScheduleBySignalValue(
            ViewSchedule viewSchedule, List <Element> elements)
        {
            var sortedElements = new List <RowData <int> >();

            var builtInParameter = GetBuiltInParameterForElements(elements);

            if (builtInParameter == null)
            {
                return(sortedElements);
            }

            // запоминаю начальные значения в параметре
            var cachedParameterValues = new Dictionary <Element, string>();

            elements.ForEach(e =>
            {
                var parameter = e.get_Parameter(builtInParameter.Value);
                cachedParameterValues.Add(e, parameter.AsString());
            });

            const string signalValue    = "$Filled$";
            var          columnNumber   = -1;
            var          startRowNumber = -1;

            bool fieldAlreadyAdded;

            using (var transaction = new SubTransaction(viewSchedule.Document))
            {
                transaction.Start();

                // всем элементам записываем в комментарий сигнальное значение в виде двух специальных символов
                elements.ForEach(e =>
                {
                    if (e.GroupId != ElementId.InvalidElementId)
                    {
                        (e.Document.GetElement(e.GroupId) as Group)?.UngroupMembers();
                    }

                    var parameter = e.get_Parameter(builtInParameter.Value);
                    parameter.Set(signalValue);
                });

                // К спецификации добавляем поле. Код из справки, за исключением try {} catch{}
                AddFieldToSchedule(viewSchedule, builtInParameter.Value, out fieldAlreadyAdded);

                // в зависимости от количества строк в таблице сразу заполняю коллекцию "болванками" и
                // нахожу номер нужной колонки и первой строки
                var sectionData = viewSchedule.GetTableData().GetSectionData(SectionType.Body);
                var rowNumber   = 0;
                for (var r = sectionData.FirstRowNumber; r <= sectionData.LastRowNumber; r++)
                {
                    for (var c = sectionData.FirstColumnNumber; c <= sectionData.LastColumnNumber; c++)
                    {
                        var cellValue = viewSchedule.GetCellText(SectionType.Body, r, c);
                        if (cellValue.Contains(signalValue))
                        {
                            rowNumber++;
                            sortedElements.Add(new RowData <int>(rowNumber));

                            if (startRowNumber == -1)
                            {
                                startRowNumber = r;
                            }
                            if (columnNumber == -1)
                            {
                                columnNumber = c;
                            }

                            break;
                        }
                    }
                }

                transaction.Commit();
            }

            // теперь выполняю итерацию по всем элементам
            for (var index = 0; index < elements.Count; index++)
            {
                var element = elements[index];
                using (var transaction = new SubTransaction(viewSchedule.Document))
                {
                    transaction.Start();

                    if (index != 0)
                    {
                        var parameter = elements[index - 1].get_Parameter(builtInParameter.Value);

                        // возвращаю элементу значение в параметр
                        parameter.Set(signalValue);
                    }

                    {
                        // элементу стираю второй символ. Первый символ нужен, чтобы идентифицировать ячейку
                        var parameter = element.get_Parameter(builtInParameter.Value);
                        parameter.Set(string.Empty);
                    }

                    // регенерирую таблицу, чтобы обновить представление
                    viewSchedule.RefreshData();
                    viewSchedule.Document.Regenerate();

                    transaction.Commit();
                }

                // теперь смотрю какая ячейка погасла
                var sectionData = viewSchedule.GetTableData().GetSectionData(SectionType.Body);
                var rowNumber   = 0;
                for (var r = startRowNumber; r <= sectionData.LastRowNumber; r++)
                {
                    rowNumber++;
                    var cellValue = viewSchedule.GetCellText(SectionType.Body, r, columnNumber);

                    /*
                     * Начиная с версии 2022 в ячейках с разными значениями пишется <варианты>. Проверять буду по скобкам
                     */

                    if (string.IsNullOrEmpty(cellValue) || (cellValue.StartsWith("<") && cellValue.EndsWith(">")))
                    {
                        var elInRow = sortedElements.FirstOrDefault(e => e.RowNumber == rowNumber);
                        elInRow?.Items.Add(element.Id.IntegerValue);

                        break;
                    }
                }
            }

            // восстанавливаю начальные значения параметров
            using (var transaction = new SubTransaction(viewSchedule.Document))
            {
                transaction.Start();

                foreach (var pair in cachedParameterValues)
                {
                    var parameter = pair.Key.get_Parameter(builtInParameter.Value);
                    parameter.Set(pair.Value);
                }

                // если поле не было добавлено изначально, то нужно его удалить
                if (!fieldAlreadyAdded)
                {
                    RemoveFieldFromSchedule(viewSchedule, builtInParameter.Value);
                }

                transaction.Commit();
            }

            return(sortedElements);
        }
        /// <summary>
        /// Получение сортированных элементов из спецификации с установленной галочкой "Для каждого экземпляра"
        /// </summary>
        /// <param name="viewSchedule">Вид спецификации</param>
        /// <param name="elements">Элементы, полученные с этого вида</param>
        private List <Element> GetSortedElementsFromItemizedSchedule(ViewSchedule viewSchedule, List <Element> elements)
        {
            var sortedElements = new List <Element>();

            var builtInParameter = GetBuiltInParameterForElements(elements);

            if (builtInParameter == null)
            {
                return(sortedElements);
            }

            using (var transaction = new SubTransaction(viewSchedule.Document))
            {
                transaction.Start();

                // Разделитель
                const string separator = "$ElementId=";

                // Записываем Id всех элементов в параметр "Комментарий"
                elements.ForEach(e =>
                {
                    if (e.GroupId != ElementId.InvalidElementId)
                    {
                        (e.Document.GetElement(e.GroupId) as Group)?.UngroupMembers();
                    }

                    var parameter = e.get_Parameter(builtInParameter.Value);
                    parameter.Set(parameter.AsString() + separator + e.Id.IntegerValue);
                });

                // К спецификации добавляем поле. Код из справки, за исключением try {} catch{}
                AddFieldToSchedule(viewSchedule, builtInParameter.Value, out _);

                // Ну и сама магия - просто читаем получившуюся спецификацию по ячейкам и получаем
                // элементы уже в том порядке, в котором мы их видим в спецификации
                var sectionData = viewSchedule.GetTableData().GetSectionData(SectionType.Body);
                for (var r = sectionData.FirstRowNumber; r <= sectionData.LastRowNumber; r++)
                {
                    for (var c = sectionData.FirstColumnNumber; c <= sectionData.LastColumnNumber; c++)
                    {
                        var cellValue = viewSchedule.GetCellText(SectionType.Body, r, c);
                        if (cellValue.Contains(separator))
                        {
                            var idStr = cellValue.Split(separator.ToCharArray()).Last();
                            if (!string.IsNullOrEmpty(idStr))
                            {
                                // Делаем устойчивым к ошибкам - при наличии ошибок все равно код завершится,
                                // а я буду знать о возможных проблемах. На мой взгляд лучше, чем полное прерывание метода
                                try
                                {
                                    sortedElements.Add(viewSchedule.Document.GetElement(new ElementId(Convert.ToInt32(idStr))));
                                }
                                catch (Exception exception)
                                {
                                    ExceptionBox.Show(exception);
                                }
                            }
                        }
                    }
                }

                // Откатываем транзакцию
                transaction.RollBack();
            }

            return(sortedElements);
        }
Example #13
0
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            Document doc = commandData.Application.ActiveUIDocument.Document;

            // Variables to store user input
            List <int> listIds;
            string     desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);

            // Variables to store log
            var schedSuccess = new List <string>();
            var schedFail    = new List <string>();

            // Prompt window to collect user input
            using (BrowserCheckboxes customWindow = new BrowserCheckboxes(commandData))
            {
                customWindow.ShowDialog();
                listIds = customWindow.listIds;
            }

            // Check there are schedules selected
            if (listIds != null)
            {
                using (BrowserWindow browserWindow = new BrowserWindow())
                {
                    browserWindow.ShowDialog();

                    // Variables
                    string fullPath = browserWindow.selectedPath;

                    // CHeck that path is not empty and path is a folder
                    if (fullPath == null || !Directory.Exists(fullPath))
                    {
                        TaskDialog.Show("Warning", "No folder has been selected");
                        return(Result.Cancelled);
                    }
                    else
                    {
                        // Loop through each selected schedule
                        foreach (int id in listIds)
                        {
                            // Extract data from schedule
                            ViewSchedule     sched       = doc.GetElement(new ElementId(id)) as ViewSchedule;
                            TableData        tD          = sched.GetTableData();
                            TableSectionData sectionData = tD.GetSectionData(SectionType.Body);
                            int numbRows = sectionData.NumberOfRows;
                            int numbCols = sectionData.NumberOfColumns;

                            // Name of the file
                            string excelPath = fullPath + @"\" + sched.Name + ".xlsx";

                            // Create excel file
                            SXSSFWorkbook workbook   = new SXSSFWorkbook();
                            SXSSFSheet    excelSheet = (SXSSFSheet)workbook.CreateSheet(sched.Name);
                            excelSheet.SetRandomAccessWindowSize(100);

                            //Create a header row
                            IRow row = excelSheet.CreateRow(0);

                            // Define format for cells
                            var fontStyle = workbook.CreateFont();
                            fontStyle.IsBold             = true;
                            fontStyle.FontHeightInPoints = 12;
                            var titleStyle = workbook.CreateCellStyle();
                            titleStyle.SetFont(fontStyle);

                            // Write to excel
                            using (var fs = new FileStream(excelPath, FileMode.Create, FileAccess.Write))
                            {
                                // Write content
                                for (int i = 0; i < numbRows; i++)
                                {
                                    row = excelSheet.CreateRow(i);

                                    for (int j = 0; j < numbCols; j++)
                                    {
                                        string content = sched.GetCellText(SectionType.Body, i, j);
                                        var    cell    = row.CreateCell(j);
                                        cell.SetCellValue(content);

                                        if (i == 0)
                                        {
                                            cell.CellStyle = titleStyle;
                                        }
                                    }
                                }

                                // Size columns
                                excelSheet.TrackAllColumnsForAutoSizing();
                                for (int i = 0; i < numbCols; i++)
                                {
                                    excelSheet.AutoSizeColumn(i);
                                }
                                excelSheet.UntrackAllColumnsForAutoSizing();

                                // Write to file
                                try
                                {
                                    workbook.Write(fs);
                                    // Log success export schedule name
                                    schedSuccess.Add(sched.Name);
                                }
                                catch
                                {
                                    schedFail.Add(sched.Name);
                                }
                            }
                        }

                        TaskDialog.Show("Success", "The following schedules have been exported: " +
                                        string.Join("\n", schedSuccess.ToArray()));

                        return(Result.Succeeded);
                    }
                }
            }

            return(Result.Cancelled);
        }
Example #14
0
        private RevitDataTable GetRevitDataTable(ViewSchedule schedule)
        {
            ScheduleDefinition scheduleDefinition = schedule.Definition;
            TableSectionData   bodyData           = schedule.GetTableData().GetSectionData(SectionType.Body);
            TableSectionData   headerData         = schedule.GetTableData().GetSectionData(SectionType.Header);

            RevitDataTable   dataTable   = new RevitDataTable(schedule.Name);
            RevitDataSection dataSection = new RevitDataSection("Без названия");

            dataTable.Sections.Add(dataSection);
            // заголовки
            int start_i;

            if (scheduleDefinition.ShowHeaders)
            {
                RevitDataRow header = new RevitDataRow(0);
                for (int col = 0; col < bodyData.NumberOfColumns; col++)
                {
                    RevitDataCell dataCell = new RevitDataCell(
                        schedule.GetCellText(SectionType.Body, 0, col),
                        bodyData.GetCellType(0, col),
                        bodyData.GetCellParamId(col));
                    header.Cells.Add(dataCell);
                }
                start_i          = 1;
                dataTable.Header = header;
            }
            else
            {
                start_i = 0;
            }
            //ищем секции
            for (int row = start_i; row < bodyData.NumberOfRows; row++)
            {
                if (bodyData.GetCellType(row, 0) == CellType.Text &&
                    bodyData.GetMergedCell(row, 0).Right == bodyData.LastColumnNumber)
                {
                    string header = bodyData.GetCellText(row, 0);
                    header      = string.IsNullOrEmpty(header) ? "Без названия" : header;
                    dataSection = new RevitDataSection(header);
                    dataTable.Sections.Add(dataSection);
                    continue;
                }

                RevitDataRow dataRow = new RevitDataRow(row);
                for (int col = 0; col < bodyData.NumberOfColumns; col++)
                {
                    RevitDataCell dataCell = new RevitDataCell(
                        schedule.GetCellText(SectionType.Body, row, col),
                        bodyData.GetCellType(row, col),
                        bodyData.GetCellParamId(col));
                    dataRow.Cells.Add(dataCell);
                }
                dataSection.Rows.Add(dataRow);
            }
            if (dataTable["Без названия"].Rows.Count == 0)
            {
                dataTable.Sections.Remove(dataTable["Без названия"]);
            }
            return(dataTable);
        }
        public void ParseSchedule(ViewSchedule schedule, string filePath, string fileHash, bool isOnSheet)
        {
            if (!schedule.IsTitleblockRevisionSchedule && !schedule.IsTemplate && schedule.Definition.ShowHeaders)
            {
                var scheduleFieldIds      = schedule.Definition.GetFieldOrder();
                List <ScheduleLine> lines = new List <ScheduleLine>();

                var indexCount = 0;
                for (int i = 0; i < scheduleFieldIds.Count; i++)
                {
                    var scheduleField = schedule.Definition.GetField(scheduleFieldIds[i]);

                    if (scheduleField.IsHidden)
                    {
                        continue;
                    }

                    var idString = string.Empty;
                    var isShared = false;

                    if (scheduleField.ParameterId.IntegerValue > 0)
                    {
                        var elem = schedule.Document.GetElement(scheduleField.ParameterId);

                        if (elem is SharedParameterElement)
                        {
                            SharedParameterElement shElem = elem as SharedParameterElement;
                            idString = shElem.GuidValue.ToString();
                            isShared = true;
                        }
                    }

                    var scheduleLine = new ScheduleLine()
                    {
                        Filepath             = filePath,
                        Filename             = Path.GetFileName(filePath),
                        Hash                 = fileHash,
                        ScheduleTitle        = schedule.Name,
                        IsOnSheet            = isOnSheet,
                        OriginalColumnHeader = scheduleField.ColumnHeading.Trim(),
                        ParameterName        = scheduleField.GetName().Trim(),
                        SharedParameterGuid  = idString,
                        FieldType            = scheduleField.FieldType,
                        IsShared             = isShared,
                        ColumnIndex          = indexCount
                    };

                    lines.Add(scheduleLine);
                    indexCount++;
                }

                var sectionData = schedule.GetTableData().GetSectionData(SectionType.Body);

                List <int> mergedRowIndicesAcrossColumns = new List <int>();

                bool hasGrandTotal = schedule.Definition.ShowGrandTotal;
                if (hasGrandTotal)
                {
                    mergedRowIndicesAcrossColumns.Add(sectionData.LastRowNumber);
                }

                for (int col = sectionData.FirstColumnNumber; col <= sectionData.LastColumnNumber; col++)
                {
                    var columnHeaders = string.Empty;
                    var columnValues  = string.Empty;

                    var matchingLine = lines.FirstOrDefault(x => x.ColumnIndex == col);

                    if (matchingLine != null)
                    {
                        bool            isMatchingOriginalText = false;
                        TableMergedCell previousMergedData     = null;

                        var previousMergedCellTopRowNumber  = sectionData.LastRowNumber;
                        var previousMergedCellLeftRowNumber = sectionData.FirstColumnNumber;

                        //Read each cell of the column in reverse order to build up values and headers
                        for (int row = sectionData.LastRowNumber; row >= sectionData.FirstRowNumber; row--)
                        {
                            var cellText   = schedule.GetCellText(SectionType.Body, row, col);
                            var mergedData = sectionData.GetMergedCell(row, col);

                            var mergedTopLeftCellText    = sectionData.GetCellText(mergedData.Top, mergedData.Left).Trim();
                            var mergedBottomLeftCellText = sectionData.GetCellText(mergedData.Bottom, mergedData.Left).Trim();

                            bool isMergedAcrossRowsInColumn  = false;
                            bool isRowMergedAcrossAllColumns = false;

                            if (row != sectionData.LastRowNumber)
                            {
                                isMergedAcrossRowsInColumn = IsMergedInColumnOnly(mergedData, previousMergedData);
                            }

                            if (mergedData.Top == mergedData.Bottom &&
                                mergedData.Left == sectionData.FirstColumnNumber &&
                                mergedData.Right == sectionData.LastColumnNumber)
                            {
                                isRowMergedAcrossAllColumns = true;
                                mergedRowIndicesAcrossColumns.Add(row);
                            }

                            if (!isMatchingOriginalText)
                            {
                                isMatchingOriginalText = (matchingLine.OriginalColumnHeader == mergedTopLeftCellText);
                            }

                            if (isMatchingOriginalText)
                            {
                                if (isMergedAcrossRowsInColumn)
                                {
                                    //The merged column value has already been found from the previous cell's merged data; skip to next row
                                    row = mergedData.Top;
                                }
                                else
                                {
                                    columnHeaders = (!string.IsNullOrEmpty(columnHeaders))
                                                                                ? string.Format("{0}|{1}", mergedTopLeftCellText, columnHeaders)
                                                                                : mergedTopLeftCellText;
                                }
                            }
                            else
                            {
                                if (row == sectionData.FirstRowNumber && string.IsNullOrEmpty(cellText))
                                {
                                    continue;
                                }
                                else if (!isRowMergedAcrossAllColumns && !mergedRowIndicesAcrossColumns.Contains(row))
                                {
                                    columnValues = (!string.IsNullOrEmpty(columnValues))
                                                                                ? string.Format("{0}|{1}", cellText, columnValues)
                                                                                : cellText;
                                }
                            }

                            previousMergedCellTopRowNumber  = mergedData.Top;
                            previousMergedCellLeftRowNumber = mergedData.Left;

                            previousMergedData = mergedData;
                        }

                        matchingLine.DelimitedColumnHeaders = columnHeaders;
                        matchingLine.ColumnValues           = columnValues.TrimStart('|');
                    }
                }

                WriteCsv(lines);

                lines.Clear();
            }
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            string SetName       = SetNameBox.Text;
            int    selectedIndex = Cbx.SelectedIndex;

            // Read each cell and find the sheet with that number
            foreach (int num in Enumerable.Range(0, nRows))
            {
                string SchedSheetNum = viewSched.GetCellText((SectionType.Body), num, selectedIndex).ToString();

                foreach (ViewSheet sheet in sheetList)
                {
                    if (SchedSheetNum == sheet.SheetNumber)
                    {
                        viewSet.Insert(sheet);
                        break;
                    }
                }
            }



            if (viewSet.Size == 0)
            {
                SetButton.IsEnabled = false; // Disable SetButton or user may crash revit
                Utils.SimpleDialog("No sheet numbers in this column", "");
                SetButton.IsEnabled = true;
            }

            else
            {
                using (Transaction transac = new Transaction(doc))
                {
                    transac.Start("Set by index");

                    // PrintManager saves the set and selects it
                    PrintManager printManager = doc.PrintManager;
                    printManager.PrintRange = PrintRange.Select;

                    ViewSheetSetting viewSheetSetting = printManager.ViewSheetSetting;
                    viewSheetSetting.CurrentViewSheetSet.Views = viewSet;

                    bool flag = false;
                    try
                    {
                        viewSheetSetting.SaveAs(SetName);
                        flag = true;
                    }

                    // Set already exists
                    catch (Autodesk.Revit.Exceptions.InvalidOperationException ex)
                    {
                        TaskDialog mainDialog = new TaskDialog("ASG");
                        mainDialog.TitleAutoPrefix = false;
                        mainDialog.MainInstruction = "Replace existing set?";
                        mainDialog.CommonButtons   = TaskDialogCommonButtons.Yes | TaskDialogCommonButtons.No;
                        TaskDialogResult res = mainDialog.Show();

                        if (res == TaskDialogResult.Yes)
                        {
                            // Delete existing set
                            FilteredElementCollector Sheet_Set_Collector = new FilteredElementCollector(doc);

                            ViewSheetSet SetToDel = Sheet_Set_Collector.OfClass(typeof(ViewSheetSet))
                                                    .Cast <ViewSheetSet>()
                                                    .Where(i => i.Name == SetName)
                                                    .FirstOrDefault();
                            doc.Delete(SetToDel.Id);

                            viewSheetSetting.SaveAs(SetName);
                            flag = true;
                        }

                        // Else cancel
                        else
                        {
                            SetButton.IsEnabled = false;
                            SetButton.IsEnabled = true;

                            flag = false;

                            transac.RollBack();
                        }
                    }
                    finally
                    {
                        if (flag)
                        {
                            Close();
                            Utils.SimpleDialog(
                                $"Created set '{SetName}' with {viewSet.Size} sheet", "");

                            transac.Commit();
                        }
                    }
                }
            }
        }