Problem Summary
I am developing an add-in for Revit 2023 using C# and the Revit API. The goal is to export all schedules (ViewSchedules) to an Excel file, with each schedule being saved on a separate sheet. However, during the data extraction process, I encountered the following issues:
Certain fields or values are missing in the export:
Details of the Approach Used:
Data Verification in Revit:
Technical Setup:
Specific Questions
Solved! Go to Solution.
Solved by guillermogutierrezgcp. Go to Solution.
Solved by reylorente1. Go to Solution.
Can you share a sample Revit file with the custom parameter, and the code you use to extract the details? Also refer, Revit API documentation under GetCellText Method which says;
Remarks:
For standard view schedules, to read the formatted text of the cell regardless of cell type, use GetCellText(SectionType, Int32, Int32)
This script is made in Revit 2025, although I'm not sure if you can use it in 2023.Check it out and then tell me. I also use Epplus to export to excel.
I hope it helps you.
public enum SectionType
{
Header,
Body
}
/// <summary>
/// Constructs a new instance of the schedule exporter operating on the input schedule.
/// </summary>
/// <param name="input">The schedule to be exported.</param>
internal class ExportSchedule(ViewSchedule input)
{
/// <summary>
/// The schedule being exported.
/// </summary>
private readonly ViewSchedule theSchedule = input;
public void ExportToExcel()
{
// Setup file location in the Documents folder
string folder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string xlsxFile = Path.Combine(folder, ReplaceIllegalCharacters(theSchedule.Name) + ".xlsx");
try
{
// Create an object to store schedule data
var scheduleData = new
{
theSchedule.Name,
Header = GetSectionData(SectionType.Header), // Method to get header data
Body = GetSectionData(SectionType.Body) // Method to get body data
};
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
// Genera el archivo Excel usando EPPlus
using (ExcelPackage excelPackage = new ExcelPackage())
{
// Crea una nueva hoja
ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets.Add(theSchedule.Name);
// Agrega el encabezado
int row = 1; // Comienza en la primera fila
if (scheduleData.Header != null)
{
for (int col = 0; col < scheduleData.Header.Count; col++)
{
worksheet.Cells[row, col + 1].Value = string.Join(", ", scheduleData.Header[col]);
}
// Mueve a la siguiente fila
row++;
}
// Agrega el cuerpo
if (scheduleData.Body != null)
{
foreach (var bodyRow in scheduleData.Body)
{
for (int col = 0; col < bodyRow.Count; col++)
{
worksheet.Cells[row, col + 1].Value = bodyRow[col];
}
// Mueve a la siguiente fila
row++;
}
}
if (File.Exists(xlsxFile))
{
File.Delete(xlsxFile);
// Define el FileInfo con el nombre de archivo completo
FileInfo excelFile = new FileInfo(xlsxFile);
// Guarda el archivo Excel
excelPackage.SaveAs(excelFile);
}
else
{
// Define el FileInfo con el nombre de archivo completo
FileInfo excelFile = new FileInfo(xlsxFile);
// Guarda el archivo Excel
excelPackage.SaveAs(excelFile);
}
}
// Abre el archivo Excel usando Process.Start
ProcessStartInfo processStartInfo = new ProcessStartInfo
{
FileName = xlsxFile,
UseShellExecute = true // Necesario para abrir el archivo
};
Process.Start(processStartInfo);
MessageBox.Show($"Archivo Excel generado en: {xlsxFile}");
}
catch (Exception ex)
{
MessageBox.Show($"Ocurrió un error: {ex.Message}");
throw;
}
}
/// <summary>
/// Gets the section data as a list of lists based on the section type.
/// </summary>
private List<List<string>> GetSectionData(SectionType sectionType)
{
var data = new List<List<string>>();
TableSectionData sectionData = theSchedule.GetTableData().GetSectionData((int)sectionType);
int numberOfRows = sectionData.NumberOfRows;
int numberOfColumns = sectionData.NumberOfColumns;
for (int iRow = sectionData.FirstRowNumber; iRow < numberOfRows; iRow++)
{
var rowData = new List<string>();
for (int iCol = sectionData.FirstColumnNumber; iCol < numberOfColumns; iCol++)
{
// Get the cell's value
var cellValue = theSchedule.GetCellText((Autodesk.Revit.DB.SectionType)sectionType, iRow, iCol);
if (!string.IsNullOrEmpty(cellValue))
{
rowData.Add(cellValue);
}
}
data.Add(rowData);
}
return data;
}
/// <summary>
/// An utility method to replace illegal characters in the schedule name when creating the JSON file name.
/// </summary>
/// <param name="stringWithIllegalChar">The schedule name.</param>
/// <returns>The updated string without illegal characters.</returns>
private static string ReplaceIllegalCharacters(string stringWithIllegalChar)
{
char[] illegalChars = Path.GetInvalidFileNameChars();
string updated = stringWithIllegalChar;
foreach (char ch in illegalChars)
{
updated = updated.Replace(ch, '_');
}
return updated;
}
}
public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
UIApplication uiapp = commandData.Application;
View activeView = commandData.View;
if (activeView is ViewSchedule)
{
ExportSchedule exporter = new(activeView as ViewSchedule);
//bool bInteractive = app.IsJournalPlaying() ? false : true;
exporter.ExportToExcel();
return Result.Succeeded;
}
else
{
message = "Unable to proceed: Active view must be a schedule.";
return Result.Cancelled;
}
}
Hello sr, helped by your code i developed this last version.
This tool exports all Revit schedules (ViewSchedules) to a single Excel file. It prompts the user to choose the output file path and format, supporting both XLSX and XLSM files. If the file exists, new worksheets are appended; otherwise, a new file is created. Each schedule is saved as a separate worksheet named after the schedule's title, including both header and body data. The Excel file is automatically opened after the export completes. This enhances efficiency by centralizing all schedule data into one organized Excel document
Hi Gullermo, not long ago I shared a solution using Json, and then exported Excel. I also use Epplus, although you can use another library. Here I share the solution from Json to Excel.la solution to Json you can search at:
Exporting schedules to JSON
Hola Gullermo, no hace mucho compartir una solución usando Json,,para después exportar Excel. También uso Epplus, aunque se puede usa otra biblioteca. Aqui te comparto la solución desde Json a Excel.la solución a Json la puedes buscar en:
Exporting schedules to JSON:
public class ScheduleData
{
public string Name { get; set; }
public List<List<string>> Header { get; set; }
public List<List<string>> Body { get; set; }
}
internal class ExportJSONToExcel
{
public static void ConvertJsonToExcel(string jsonFilePath)
{
// Define el nombre de archivo aquí
string excelFileName = "ScheduleData.xlsx";
string excelFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), excelFileName);
try
{
// Lee el contenido del archivo JSON
string jsonData = File.ReadAllText(jsonFilePath);
// Deserializa el jsonData en un objeto ScheduleData
var schedule = JsonConvert.DeserializeObject<ScheduleData>(jsonData);
// Genera el archivo Excel usando EPPlus
using (ExcelPackage excelPackage = new ExcelPackage())
{
// Crea una nueva hoja
ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets.Add(schedule.Name);
// Agrega el encabezado
int row = 1; // Comienza en la primera fila
if (schedule.Header != null)
{
for (int col = 0; col < schedule.Header.Count; col++)
{
worksheet.Cells[row, col + 1].Value = string.Join(", ", schedule.Header[col]);
}
row++; // Mueve a la siguiente fila
}
// Agrega el cuerpo
if (schedule.Body != null)
{
foreach (var bodyRow in schedule.Body)
{
for (int col = 0; col < bodyRow.Count; col++)
{
worksheet.Cells[row, col + 1].Value = bodyRow[col];
}
row++; // Mueve a la siguiente fila
}
}
// Define el FileInfo con el nombre de archivo completo
FileInfo excelFile = new FileInfo(excelFilePath);
// Guarda el archivo Excel
excelPackage.SaveAs(excelFile);
}
// Abre el archivo Excel usando Process.Start
ProcessStartInfo processStartInfo = new ProcessStartInfo
{
FileName = excelFilePath,
UseShellExecute = true // Necesario para abrir el archivo
};
Process.Start(processStartInfo);
MessageBox.Show($"Archivo Excel generado en: {excelFilePath}");
}
catch (Exception ex)
{
MessageBox.Show($"Ocurrió un error: {ex.Message}");
}
}
}
Can't find what you're looking for? Ask the community or share your knowledge.