Import / export
/export-msproject reads and writes MS Project XML (MSPDI) with no dependencies — the same lazy-entry shape as /export-excel (exceljs peer), /export-pdf (jspdf peer) and /export-image, which the overview demonstrates. Every exporter reads getExportData().
MS Project XML .xml export .xml import Excel PDF PNG
MS Project XML
Download the plan as .xml — tasks with WBS and outline levels, constraints, deadlines and baselines, links with their lag, resources with max units, assignments with units and the calendar — or import a sample file. The reader is a small DOM-free tokenizer (no Trusted Types sink, no DTD entities); its result binds straight to the inputs.
exportGanttToMsProject importMsProjectXml LinkLag
Task
Start
End
Duration
Platform
Aug 3
Aug 15
12d
API design
Aug 3
Aug 7
4d
Database
Aug 5
Aug 11
6d
Monitoring
Aug 6
Aug 10
4d
Load tests
Aug 11
Aug 14
3d
Hand-over
Aug 14
Aug 15
1d
August 2026August 2026August 2026August 2026August 2026September 2026September 2026September 2026September 2026October 2026
2345678910111213141516171819202122232425262728293031123456789101112131415161718192021222324252627282930123456
import { ChangeDetectionStrategy, Component, signal, viewChild } from '@angular/core';
import { OgeGantt } from '@oge-ui/gantt';
import type { OgeGanttResource, OgeGanttWorkCalendar } from '@oge-ui/gantt';
@Component({
selector: 'demo-root',
imports: [OgeGantt],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<!-- /export-msproject has no dependencies: MSPDI XML with WBS, outline
levels, manual mode, constraints, deadlines, baselines, links with lag,
resources, assignments with units and the calendar. The import returns
plain data in the default field names — bind it. -->
<div class="mb-3 flex flex-wrap gap-2">
<button type="button" (click)="exportXml()">Download .xml</button>
<input type="file" accept=".xml" (change)="importXml($event)" />
</div>
<oge-gantt
#gantt
[tasks]="tasks()"
[dependencies]="links()"
[resources]="resources()"
[workCalendar]="calendar()"
style="height: 420px"
/>
`,
})
export class Demo {
protected readonly gantt = viewChild.required<OgeGantt<Record<string, unknown>>>('gantt');
protected readonly tasks = signal<Record<string, unknown>[]>([
{ id: 1, title: 'Pack', start: new Date(2026, 7, 3), end: new Date(2026, 7, 6) },
{ id: 2, title: 'Move', start: new Date(2026, 7, 7), end: new Date(2026, 7, 8) },
]);
protected readonly links = signal<Record<string, unknown>[]>([
{ id: 'a', predecessorId: 1, successorId: 2, lag: 1 },
]);
protected readonly resources = signal<OgeGanttResource[]>([]);
protected readonly calendar = signal<OgeGanttWorkCalendar | null>(null);
protected async exportXml(): Promise<void> {
const { exportGanttToMsProject } = await import('@oge-ui/gantt/export-msproject');
exportGanttToMsProject(this.gantt(), { filename: 'plan.xml', title: 'Office move' });
}
protected async importXml(event: Event): Promise<void> {
const file = (event.target as HTMLInputElement).files?.[0];
if (!file) return;
const { importMsProjectXml } = await import('@oge-ui/gantt/export-msproject');
const plan = importMsProjectXml(await file.text());
this.tasks.set(plan.tasks as unknown as Record<string, unknown>[]);
this.links.set(plan.dependencies as unknown as Record<string, unknown>[]);
this.resources.set(plan.resources);
this.calendar.set(plan.workCalendar);
}
}