One of the tools I designed is aimed at the mass creation of schedules based on selected assemblies.
The tool generally works fine, taking a template as an input value and associating it with the created schedules. This template has specific formatting for the schedule title.
However, an issue has been observed when using the tool: even though it correctly creates the schedules and associates the View Template, if the project is saved and closed without opening a schedule created by the tool, upon reopening the project, the title in this schedule displays incorrect formatting. The only way to fix this is to change the title formatting in the template to something else and then revert it to the original formatting.
The ViewSchedule.RefreshData method during the creation of schedules fixes this issue, but it significantly increases the creation time, taking up to 8 times longer than usual. Are there other ways to work around this error? Is this a known issue in the community?
private ViewSchedule Create(string assemblyName, AssemblySchedule assemblySchedule)
{
try
{
using Transaction trans = new Transaction(doc);
trans.Start("Create schedule");
ViewSchedule schedule = GetViewSchedule(assemblySchedule.SelectedScheduleType, assemblySchedule.SelectedCategory);
if (schedule == null) { return null; }
schedule.Name = GetScheduleName(assemblyName, assemblySchedule);
var template = assemblySchedule.SelectedScheduleTemplate.View;
if (template != null) { schedule.ViewTemplateId = template.Id; }
schedule.get_Parameter(BuiltInParameter.VIEW_PHASE).Set(assemblySchedule.SelectedPhase.Id);
AddFields(schedule, assemblySchedule, assemblySchedule.SelectedCategory);
//schedule.RefreshData(); //This solves the bug, but make the code significantly slower
doc.Regenerate();
SetFilter(schedule, assemblyName, assemblySchedule.SelectedCategory);
trans.Commit();
return schedule;
}
catch
{
return null;
}
}
Any insight will be much appreciated. Thanks a lot!!
Solved! Go to Solution.
Solved by joao.rick7. Go to Solution.
First, can you provide a picture of the incorrect vs correct formatting? Second, try running the code without doc.regenerate() you shouldn't need that with the transaction.
Before anything else, thank you very much for the response. In the attached image, you can see that when RefreshData is implemented or the schedule is opened before the project is saved and closed, the title formatting is different compared to when this doesn't happen, even though both have the same template.
Regarding Doc.Regenerate(), in this specific case, it was used because the SetFilter method calls the ScheduleDefinition.GetFieldOrder method for the created schedule. For some reason, if the document is not regenerated, this method does not returns all the fields ids for schedules that have just been created.
interesting. okay what does the schedule look like when placed on sheet, refreshdata vs not?
well that's disappointing. My best guess is the combination of RefreshData and Regenerate is the cause of the slow down. if you use refresh and not regenerate, does the ScheduleDefinition.GetFieldOrder() return incorectly?
Another thought, what about re-jiggering some of the code? split the creation and setfilter into separate transactions:
private ViewSchedule Create(string assemblyName, AssemblySchedule assemblySchedule)
{
try
{
ViewSchedule schedule = GetViewSchedule(assemblySchedule.SelectedScheduleType, assemblySchedule.SelectedCategory);
using Transaction trans = new Transaction(doc);
trans.Start("Create schedule");
if (schedule == null) { return null; }
schedule.Name = GetScheduleName(assemblyName, assemblySchedule);
var template = assemblySchedule.SelectedScheduleTemplate.View;
if (template != null) { schedule.ViewTemplateId = template.Id; }
schedule.get_Parameter(BuiltInParameter.VIEW_PHASE).Set(assemblySchedule.SelectedPhase.Id);
AddFields(schedule, assemblySchedule, assemblySchedule.SelectedCategory);
schedule.RefreshData(); //This solves the bug, but make the code significantly slower
trans.Commit();
doc.Regenerate(); //with it split, may not need the regen
using transaction trans2 = new transaction(doc)
trans2.Start("modify sched")
SetFilter(schedule, assemblyName, assemblySchedule.SelectedCategory);
trans2.Commit()
return schedule;
}
catch
{
return null;
}
}
Hi @joao.rick7,
This could be due to the Schedule is created AND attached a template in a single transaction.
For some elements to update correctly they first need to be committed to the database before a edit can be performed, and can cause such behaviour as the viewtemplate not updating the schedule until a change occurs in the template. This could be such case.
Try using a Transaction group and within 2 transaction, where in the first transaction create the schedule(s) and commit it. Then start the second transaction and attach the template to the earlies created schedules.
And at last assimilate the transactiongroup. (see: https://www.revitapidocs.com/2024/f1113d30-4c36-7844-1537-aad7f095cea0.htm )
- Michel
Thanks both to @ctm_mka and @TripleM-Dev.net for the answers, appreciate it! Surprisingly, even when using a new transaction, the bug keeps showing. Furthermore, Doc.Regenerate needs to be maintained even with the creation of a new transaction. In any case, the code I tested, following the suggestion, was:
private ViewSchedule Create(string assemblyName, AssemblySchedule assemblySchedule)
{
try
{
using TransactionGroup transGroup = new(doc);
transGroup.Start("Create Schedule");
ViewSchedule schedule = null;
using (Transaction trans = new Transaction(doc))
{
trans.Start("ViewSchedule Creation"); //Creation of Schedule without Template
schedule = GetViewSchedule(assemblySchedule.SelectedScheduleType, assemblySchedule.SelectedCategory);
if (schedule == null) { return null; }
schedule.Name = GetScheduleName(assemblyName, assemblySchedule);
schedule.get_Parameter(BuiltInParameter.VIEW_PHASE).Set(assemblySchedule.SelectedPhase.Id);
trans.Commit();
}
using (Transaction trans2 = new Transaction(doc))
{
trans2.Start("Changes ViewSchedule"); //Changes the schedule template
var template = assemblySchedule.SelectedScheduleTemplate.View;
if (template != null) { schedule.ViewTemplateId = template.Id; }
AddFields(schedule, assemblySchedule, assemblySchedule.SelectedCategory);
//The code should implement Doc.Regenerate here
SetFilter(schedule, assemblyName, assemblySchedule.SelectedCategory);
trans2.Commit();
}
transGroup.Assimilate();
return schedule;
}
catch
{
return null;
}
}
And the result:
well then. if you put back the doc regen where its needed, hows the speed compared to the old code?
And what If you set the filter of the schedule to something that wouldn't result in elements
Something simple...like FamilyName Equal "_" (and commit the transaction)
Call RefreshData (should speed up the refresh with no elements to show and a quickFilter), then set the correct filter in a new transaction and commit again.
And place all of this inside a Transaction group to combine the Undo actions.
I'm guessing in the UI this is automatically done because, creating a new schedule in the UI also opens it directly (= RefreshData) and a viewtemplate can only be attached afterwards.
The code doesn't seem to have a negative impact on its performance with doc.Regenerate. The field IDs are returned correctly, but the formatting bug in the template persists even after two separate translations.
A small note; don't add fields and change the template in the same transaction, best to only change the template in the second transaction.
And a advise, just create a schedule and add a field or 2 in a transaction + commit.
Then change the template in a transaction + commit.
And see if that does anything, just to eleminate any other edits disturbing it like setting the phase or filter etc..
Only after the formatting is solved I would add other edits.
First of all, I'd like to thank the users for their responses, which helped me find a way to work around this bug. The solution was to initially create a model Schedule with the desired template and fields. This "model" is then copied to create each of the other schedules using the following methods. Strangely, the RefreshData method does not need to be used in this case, and the program experiences virtually no performance detriment.
private ViewSchedule CreateModel(string assemblyName, AssemblySchedule assemblySchedule)
{
using Transaction trans = new Transaction(doc);
trans.Start("Creae schedule model");
ViewSchedule schedule = GetViewSchedule(assemblySchedule.SelectedScheduleType, assemblySchedule.SelectedCategory);
if (schedule == null) { return null; }
schedule.Name = GetScheduleName(assemblyName, assemblySchedule);
var template = assemblySchedule.SelectedScheduleTemplate.View;
if (template != null) { schedule.ViewTemplateId = template.Id; }
schedule.get_Parameter(BuiltInParameter.VIEW_PHASE).Set(assemblySchedule.SelectedPhase.Id);
AddFields(schedule, assemblySchedule, assemblySchedule.SelectedCategory);
doc.Regenerate();
trans.Commit();
return schedule;
}
private ViewSchedule Create(string assemblyName, ViewSchedule scheduleModel, AssemblySchedule assemblySchedule)
{
try
{
ViewSchedule schedule = doc.GetElement(scheduleModel.Duplicate(ViewDuplicateOption.Duplicate)) as ViewSchedule;
schedule.Name = GetScheduleName(assemblyName, assemblySchedule);
SetFilter(schedule, assemblyName, assemblySchedule.SelectedCategory);
return schedule;
}
catch
{
return null;
}
}
Can't find what you're looking for? Ask the community or share your knowledge.