我正在使用 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 文件中元素的参数之间建立关系,并尝试使用以下命令修改这些参数:表中的数据。
你的代码又长又难理解。该错误消息清楚地表明您正在尝试在事务之外修改文档。您在那里有一项事务,但一些修改发生在事务范围之外。我建议你清理你的代码并将其分成更小的单独的逻辑单元,以便更容易理解逻辑。