使用 C# 修改 Revit 中链接的 IFC

问题描述 投票:0回答:1

我正在使用 C# 在 Visual Studio 中开发一个自动化项目,但我的经验仍然有限,缺乏很多知识。 revit 错误脚本设法下载 IFC 文件并使用事务重新加载它,但它不会修改任何内容,并且 Revit 在所附图像中向我显示消息。我还包括了执行交易的代码部分,因为我相信这就是我犯错误的地方。我真的很感谢任何帮助。问候。

这是在链接的 IFC 上进行交易的脚本部分:

[交易(TransactionMode.手动)] 公共类 FillGeoPar :IExternalCommand { public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; 文档 doc = uidoc.Document; 应用程序app = uiapp.Application;

        try
        {
            // Obtener el diccionario de documentos vinculados IFC
            RevitLinkChecker linkChecker = new RevitLinkChecker();
            var diccDocsVinc = linkChecker.ObtenerDiccVincReload(doc, "ifc");

            // Mostrar TaskDialog con los vínculos cargados
            string vinculosCargados = string.Join("\n", diccDocsVinc.Keys);
            TaskDialog.Show("Vínculos Cargados", $"Los siguientes vínculos IFC están cargados:\n{vinculosCargados}");

            // Seleccionar archivo Excel
            string dfRuta = SeleccionarArchivoExcel();
            if (string.IsNullOrEmpty(dfRuta))
            {
                message = "No se seleccionó ningún archivo Excel.";
                return Result.Cancelled;
            }

            // Seleccionar hoja del Excel
            string dfHoja = SeleccionarHojaExcel(dfRuta);
            if (dfHoja == null)
            {
                message = "No se seleccionó ninguna hoja de Excel.";
                return Result.Cancelled;
            }

            // Obtener DataFrame del Excel
            var df = ObtenerDataFrameExcel(dfRuta, dfHoja);
            if (df == null)
            {
                message = "No se pudo obtener la hoja del archivo Excel.";
                return Result.Failed;
            }

            // Mostrar la primera columna en un diálogo
            var primeraColumna = df.AsEnumerable().Select(row => row[0].ToString()).ToList();
            TaskDialog.Show("Primera Columna", string.Join("\n", primeraColumna));

            // Descargar todos los vínculos fuera de la transacción
            var loadedExternalFilesRef = new List<RevitLinkType>();
            var collector = new FilteredElementCollector(doc);
            foreach (Element element in collector.OfClass(typeof(RevitLinkType)))
            {
                ExternalFileReference extFileRef = element.GetExternalFileReference();
                if (extFileRef == null || extFileRef.GetLinkedFileStatus() != LinkedFileStatus.Loaded)
                    continue;

                var revitLinkType = (RevitLinkType)element;
                loadedExternalFilesRef.Add(revitLinkType);
                revitLinkType.Unload(null);
            }

            // Reabrir los vínculos y modificar parámetros
            foreach (var revitLinkType in loadedExternalFilesRef)
            {
                // Obtener la ruta del archivo vinculado
                ExternalFileReference extFileRef = revitLinkType.GetExternalFileReference();
                string rutaVinc = ModelPathUtils.ConvertModelPathToUserVisiblePath(extFileRef.GetAbsolutePath());

                // Abrir el documento del vínculo
                Document linkDoc = app.OpenDocumentFile(rutaVinc);

                // Verificar y asignar los parámetros de los elementos vinculados que coinciden con las columnas del Excel
                using (Transaction trans = new Transaction(linkDoc, "Modificar Parámetros Elementos Vinculados"))
                {
                    trans.Start();

                    var nombresColumnasIFC = VerificarColumnasIFC(diccDocsVinc, df, linkDoc);

                    var colector = new FilteredElementCollector(linkDoc)
                        .WhereElementIsNotElementType()
                        .ToList();

                    foreach (var element in colector)
                    {
                        IList<Parameter> parametros = element.GetOrderedParameters();
                        Parameter nombreCodigoParam = parametros.FirstOrDefault(p => p.Definition != null && p.Definition.Name.Contains("NombreCódigo"));

                        if (nombreCodigoParam != null)
                        {
                            string nombreCodigo = nombreCodigoParam.AsString();

                            if (!string.IsNullOrEmpty(nombreCodigo) && primeraColumna.Contains(nombreCodigo))
                            {
                                DataRow filaExcel = df.AsEnumerable().FirstOrDefault(row => row[0].ToString() == nombreCodigo);

                                if (filaExcel != null)
                                {
                                    foreach (Parameter param in parametros)
                                    {
                                        if (param.Definition != null)
                                        {
                                            string paramName = param.Definition.Name;

                                            string columna = nombresColumnasIFC.FirstOrDefault(col => paramName.EndsWith(col, StringComparison.OrdinalIgnoreCase));

                                            if (columna != null && df.Columns.Contains(columna))
                                            {
                                                string valorExcel = filaExcel[columna].ToString();

                                                if (!string.IsNullOrEmpty(valorExcel))
                                                {
                                                    if (param.StorageType == StorageType.String)
                                                    {
                                                        param.Set(valorExcel);
                                                    }
                                                    else if (param.StorageType == StorageType.Double && double.TryParse(valorExcel, out double valorDouble))
                                                    {
                                                        param.Set(valorDouble);
                                                    }
                                                    else if (param.StorageType == StorageType.Integer && int.TryParse(valorExcel, out int valorInt))
                                                    {
                                                        param.Set(valorInt);
                                                    }
                                                    else if (param.StorageType == StorageType.ElementId && int.TryParse(valorExcel, out int valorElementId))
                                                    {
                                                        param.Set(new ElementId(valorElementId));
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    trans.Commit();
                }

                // Cerrar el documento del vínculo
                linkDoc.Close(false);

                // Recargar el vínculo
                revitLinkType.Load();
            }

            // Regenerar el documento principal
            doc.Regenerate();

            TaskDialog.Show("Éxito", "Parámetros modificados y guardados correctamente.");
            return Result.Succeeded;
        }
        catch (Exception ex)
        {
            message = ex.Message;
            return Result.Failed;
        }
    }

我正在尝试开发的脚本涉及为 Revit 创建一个加载项,该加载项通过链接的 IFC 文件在 Excel 表格中的数据与此 IFC 文件中元素的参数之间建立关系,并尝试使用以下命令修改这些参数:表中的数据。

c# excel revit-api ifc
1个回答
0
投票

你的代码又长又难理解。该错误消息清楚地表明您正在尝试在事务之外修改文档。您在那里有一项事务,但一些修改发生在事务范围之外。我建议你清理你的代码并将其分成更小的单独的逻辑单元,以便更容易理解逻辑。

© www.soinside.com 2019 - 2024. All rights reserved.