首页 > 其他分享 >甘特图的这些新玩法,你都知道吗?

甘特图的这些新玩法,你都知道吗?

时间:2023-11-15 14:04:41浏览次数:37  
标签:function ganttSheet 玩法 甘特图 project getElementById spread var 知道


前言

甘特图是项目管理、生产排程、节点管理中非常常见的一个功能。那么,有没有一种方法能够帮助将甘特图引入到系统中,让数据的进度、排程数据的展示更加直观,让管理更加高效。

本葡萄今天为大家带来一个新的插件——甘特图插件。该插件是结合 SpreadJS 本身强大电子表格能力提供的一种全新的可视化展示方案,能够有效地将生产计划、预算排期中的日程管理信息展示出来,显示关键路径上关键节点的进展或状态。其数据来自与集算表同源的数据管理器(DataManager),通过绑定 -> 视图的方式,将层级化的任务数据通过甘特图插件进行展示。

甘特图的这些新玩法,你都知道吗?_数据

(通过甘特图插件展示层级化的数据)

1. 缩放和时间刻度滚动

甘特图的这些新玩法,你都知道吗?_甘特图_02

(通过甘特图插件实现缩放及刻度滚动)

JavaScript代码:

var myTable;
var ganttSheet;
var adjustTierUnit = true;

window.onload = function() {
    var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 0 });
    initSpread(spread);
    initSplitView(spread);
};

function initSpread(spread) {
    spread.suspendPaint();
    initDataSource(spread);
    initGanttSheet(spread);
    spread.resumePaint();
}

function initDataSource(spread) {
    var tableName = "Gantt_Id";
    var baseApiUrl = getBaseApiUrl();
    var apiUrl = baseApiUrl + "/" + tableName;
    var dataManager = spread.dataManager();
    myTable = dataManager.addTable("myTable", {
        batch: true,
        remote: {
            read: {
                url: apiUrl
            }
        },
        schema: {
            hierarchy: {
                type: "Parent",
                column: "parentId"
            },
            columns: {
                id: { isPrimaryKey: true },
                taskNumber: { dataType: "rowOrder" }
            }
        }
    });
}

function initGanttSheet(spread) {
    ganttSheet = spread.addSheetTab(0, "GanttSheet", GC.Spread.Sheets.SheetType.ganttSheet);
    var view = myTable.addView("ganttView", [
        { value: "taskNumber", caption: "NO.", width: 60 },
        { value: "name", caption: "Task Name", width: 200 },
        { value: "duration", caption: "Duration", width: 90 },
        { value: "predecessors", caption: "Predecessors", width: 120 }
    ]);
    view.fetch().then(function() {
        ganttSheet.bindGanttView(view);
    }).then(function() {
        ganttSheet.project.timescale.zoomOut();
    });
    initSidePanel(ganttSheet);
}

2.任务栏和网格线的样式调整

甘特图的这些新玩法,你都知道吗?_甘特图_03

(通过甘特图插件实现的任务栏和网格线的样式)

JavaScript代码:

/*REPLACE_MARKER*/
/*DO NOT DELETE THESE COMMENTS*/
var myTable;
var ganttSheet;

window.onload = function() {
    var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 0 });
    initSpread(spread);
    initSplitView(spread);
};

function initSpread(spread) {
    spread.suspendPaint();
    initDataSource(spread);
    initGanttSheet(spread);
    spread.resumePaint();
}

function initDataSource(spread) {
    var tableName = "Gantt_Id";
    var baseApiUrl = getBaseApiUrl();
    var apiUrl = baseApiUrl + "/" + tableName;
    var dataManager = spread.dataManager();
    myTable = dataManager.addTable("myTable", {
        batch: true,
        remote: {
            read: {
                url: apiUrl
            }
        },
        schema: {
            hierarchy: {
                type: "Parent",
                column: "parentId"
            },
            columns: {
                id: { isPrimaryKey: true },
                taskNumber: { dataType: "rowOrder" }
            }
        }
    });
}

function initGanttSheet(spread) {
    ganttSheet = spread.addSheetTab(0, "GanttSheet", GC.Spread.Sheets.SheetType.ganttSheet);
    var view = myTable.addView("ganttView", [
        { value: "taskNumber", caption: "NO.", width: 60 },
        { value: "name", caption: "Task Name", width: 200 },
        { value: "duration", caption: "Duration", width: 90 },
        { value: "predecessors", caption: "Predecessors", width: 120, visible: false }
    ]);
    view.fetch().then(function() {
        ganttSheet.bindGanttView(view);
        ganttSheet.project.timescale.tierMode = GC.Spread.Sheets.GanttSheet.TimescaleTierMode.topMiddleBottom;
        ganttSheet.project.timescale.topTier.unit = GC.Spread.Sheets.GanttSheet.TimescaleUnit.thirdsOfMonth;
    }).then(function() {
        ganttSheet.gridlines.bottomTierColumn = {
            lineType: GC.Spread.Sheets.GanttSheet.GanttGridlineType.dashed,
            lineColor: "#c85b11"
        };
        ganttSheet.gridlines.ganttRows.lineType = GC.Spread.Sheets.GanttSheet.GanttGridlineType.thin;
        ganttSheet.gridlines.ganttRows.lineColor = "#abd08f";
        ganttSheet.gridlines.ganttRows.interval = 2;
        ganttSheet.gridlines.ganttRows.intervalLineType = GC.Spread.Sheets.GanttSheet.GanttGridlineType.dashDot;
        ganttSheet.gridlines.ganttRows.intervalLineColor = "#9cc3e5";
    });
    initSidePanel(ganttSheet);
}

function initSidePanel(ganttSheet) {
    var setButton = document.getElementById("set-gridline");
    var intervalPanel = document.getElementById("interval-panel");
    var affectItemOption = document.getElementById("affectItem");
    var lineTypeOption = document.getElementById("lineType");
    var lineColorOption = document.getElementById("lineColor");
    var intervalLineTypeOption = document.getElementById("intervalLineType");
    var intervalLineColorOption = document.getElementById("intervalLineColor");
    var intervalOption = document.getElementById("interval");

    var option = convertToNormalOptions(ganttSheet, "ganttRows");
    syncOptionToPanel(option);

    affectItemOption.addEventListener('change', function(e) {
        var target = affectItemOption.value;
        if (affectItemOption.value === "ganttRows") {
            intervalPanel.classList.remove("hide");
        } else {
            intervalPanel.classList.add("hide");
        }
        var option = convertToNormalOptions(ganttSheet, target);
        syncOptionToPanel(option);
    });
    setButton.addEventListener('click', function() {
        var target = affectItemOption.value;
        var lineType = Number(lineTypeOption.value);
        var lineColor = lineColorOption.value;
        var intervalLineType = Number(intervalLineTypeOption.value);
        var intervalLineColor = intervalLineColorOption.value;
        var interval = Number(intervalOption.value);
        var option = convertToGanttGridlineOptions(lineType, lineColor, intervalLineType, intervalLineColor, interval);
        if (option) {
            ganttSheet.gridlines[target] = option;
        }
    });

3.数据展示布局调整

甘特图的这些新玩法,你都知道吗?_ide_04

(通过甘特图插件实现布局的调整)

JavaScript代码:

/*REPLACE_MARKER*/
/*DO NOT DELETE THESE COMMENTS*/
var myTable;
var ganttSheet;
var roundBarsToWholeDays = true;

window.onload = function() {
    var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 0 });
    initSpread(spread);
    initSplitView(spread);
};

function initSpread(spread) {
    spread.suspendPaint();
    initDataSource(spread);
    initGanttSheet(spread);
    spread.resumePaint();
}

function initDataSource(spread) {
    var tableName = "Gantt_Id";
    var baseApiUrl = getBaseApiUrl();
    var apiUrl = baseApiUrl + "/" + tableName;
    var dataManager = spread.dataManager();
    myTable = dataManager.addTable("myTable", {
        batch: true,
        remote: {
            read: {
                url: apiUrl
            }
        },
        schema: {
            hierarchy: {
                type: "Parent",
                column: "parentId"
            },
            columns: {
                id: { isPrimaryKey: true },
                taskNumber: { dataType: "rowOrder" }
            }
        }
    });
}

function initGanttSheet(spread) {
    ganttSheet = spread.addSheetTab(0, "GanttSheet", GC.Spread.Sheets.SheetType.ganttSheet);
    var view = myTable.addView("ganttView", [
        { value: "taskNumber", caption: "NO.", width: 60 },
        { value: "name", caption: "Task Name", width: 200 },
        { value: "duration", caption: "Duration", width: 90 },
        { value: "predecessors", caption: "Predecessors", width: 120, visible: false }
    ]);
    view.fetch().then(function() {
        ganttSheet.bindGanttView(view);
        ganttSheet.suspendPaint();
        var summaryStyleRule = ganttSheet.project.taskStyleRules.getRule("summary");
        var summaryStyle = summaryStyleRule.style.taskbarStyle;
        summaryStyle.leftText = "start";
        summaryStyle.rightText = "finish";
        summaryStyleRule.style.taskbarStyle = summaryStyle;
        var layout = ganttSheet.project.layout;
        layout.linkLineMode = "noLinks";
        layout.barHeight = 18;
        ganttSheet.resumePaint();
    });
    initSidePanel(ganttSheet);
}

function initSidePanel(ganttSheet) {
    var roundBarItem = document.getElementById("round-bar");
    var linkTypeItem = document.getElementById("link-type");
    var barHeightItem = document.getElementById("bar-height");
    var dateFormatItem = document.getElementById("date-format");
    var setLayoutItem = document.getElementById("set-layout");

    roundBarItem.addEventListener("click", function() {
        if (roundBarItem.classList.contains("active")) {
            roundBarItem.classList.remove("active");
            roundBarsToWholeDays = false;
        } else {
            roundBarItem.classList.add("active");
            roundBarsToWholeDays = true;
        }
    });

    setLayoutItem.addEventListener("click", function() {
        var layout = ganttSheet.project.layout;
        ganttSheet.suspendPaint();
        layout.linkLineMode = linkTypeItem.value;
        layout.barHeight = Number(barHeightItem.value);
        layout.barTextDateFormat = dateFormatItem.value;
        layout.roundBarsToWholeDays = roundBarsToWholeDays;
        ganttSheet.resumePaint();
    });
}

4.任务操作

甘特图的这些新玩法,你都知道吗?_ide_05

(可在甘特图插件实现任务操作)

JavaScript代码:

/*REPLACE_MARKER*/
/*DO NOT DELETE THESE COMMENTS*/
var myTable;
var ganttSheet;
var roundBarsToWholeDays = true;

window.onload = function () {
    var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 0 });
    initSpread(spread);
    initSplitView(spread);
};

function initSpread(spread) {
    spread.suspendPaint();
    initDataSource(spread);
    initGanttSheet(spread);
    spread.resumePaint();
}

function initDataSource(spread) {
    var tableName = "Gantt_Id";
    var baseApiUrl = getBaseApiUrl();
    var apiUrl = baseApiUrl + "/" + tableName;
    var dataManager = spread.dataManager();
    myTable = dataManager.addTable("myTable", {
        batch: true,
        remote: {
            read: {
                url: apiUrl
            },
            batch: {
                url: apiUrl + "Collection"
            }
        },
        schema: {
            hierarchy: {
                type: "Parent",
                column: "parentId"
            },
            columns: {
                id: { isPrimaryKey: true },
                taskNumber: { dataType: "rowOrder" }
            }
        }
    });
}

function initGanttSheet(spread) {
    ganttSheet = spread.addSheetTab(0, "GanttSheet", GC.Spread.Sheets.SheetType.ganttSheet);
    var view = myTable.addView("ganttView", [
        { value: "id", caption: "Id", width: 40 },
        { value: "taskNumber", caption: "NO.", width: 60 },
        { value: "name", caption: "Task Name", width: 200 },
        { value: "duration", caption: "Duration", width: 90 },
        { value: "predecessors", caption: "Predecessors", width: 120 }
    ]);
    view.fetch().then(function () {
        ganttSheet.bindGanttView(view);
    });
    initSidePanel(ganttSheet);
}

function initSidePanel(ganttSheet) {
    var addTaskItem = document.getElementById("add-task");
    var addSummayItem = document.getElementById("add-summary");
    var addMilestoneItem = document.getElementById("add-milestone");

    var deleteItem = document.getElementById("delete-task");

    var indentTaskItem = document.getElementById("indent-task");
    var outdentTaskItem = document.getElementById("outdent-task");

    var linkTaskItem = document.getElementById("link-task");
    var unlinkTaskItem = document.getElementById("unlink-task");

    var submitItem = document.getElementById("submit-changes");
    var cancelItem = document.getElementById("cancel-changes");

    addTaskItem.addEventListener("click", function () {
        ganttSheet.suspendPaint()
        addTask();
        ganttSheet.resumePaint();
    });
    addSummayItem.addEventListener("click", function () {
        ganttSheet.suspendPaint()
        addSummary();
        ganttSheet.resumePaint();
    });
    addMilestoneItem.addEventListener("click", function () {
        ganttSheet.suspendPaint()
        addMilestone();
        ganttSheet.resumePaint();
    });

    deleteItem.addEventListener("click", function () {
        ganttSheet.suspendPaint()
        deleteTask();
        ganttSheet.resumePaint();
    });

    indentTaskItem.addEventListener("click", function () {
        ganttSheet.suspendPaint()
        indentTask();
        ganttSheet.resumePaint();
    });
    outdentTaskItem.addEventListener("click", function () {
        ganttSheet.suspendPaint()
        outdentTask();
        ganttSheet.resumePaint();
    });

    linkTaskItem.addEventListener("click", function () {
        ganttSheet.suspendPaint()
        linkTask();
        ganttSheet.resumePaint();
    });
    unlinkTaskItem.addEventListener("click", function () {
        ganttSheet.suspendPaint()
        unlinkTask();
        ganttSheet.resumePaint();
    });

    submitItem.addEventListener("click", function () {
        ganttSheet.submitChanges();
    });
    cancelItem.addEventListener("click", function () {
        ganttSheet.cancelChanges();
    });

    function addTask() {
        var project = ganttSheet.project;
        var selections = ganttSheet.getSelections();
        var insertedRow = Math.min(...selections.map(r => r.row), project.tasks.length)
        var rowCount = selections.map(r => r.rowCount).reduce((pre, current) => { return pre + current });
        var taskData = createTaskDataList(rowCount, () => ({ name: "<新任务>" }));
        project.insertTasksByRow(insertedRow, taskData);
    }

    function addSummary() {
        var project = ganttSheet.project;
        var selectedRange = ganttSheet.getSelections()[0];
        var insertedRow = selectedRange.row;
        var insertedTaskNumbers = ganttSheet.getTaskByRow(insertedRow).taskNumber || project.count;
        var selectedTasks = getSelectedRowIndexes().map((row) => ganttSheet.getTaskByRow(row)).filter((row) => !!row);

        if (selectedTasks.length == 0) {
            project.insertTasks(insertedTaskNumbers, [{ name: "<新摘要任务>" }, { name: "<新任务>" }]);
            project.indentTasks(insertedTaskNumbers + 1);
        } else {
            project.insertTasks(insertedTaskNumbers, { name: "<新摘要任务>" }, selectedTasks[0].level);
            project.indentTasks(selectedTasks.map((t) => t.taskNumber));
        }
        ganttSheet.setSelection(insertedRow, -1, 1, -1);
    }

    function addMilestone() {
        var project = ganttSheet.project;
        var selections = ganttSheet.getSelections();
        var rowCount = selections.map(r => r.rowCount).reduce((pre, current) => { return pre + current });
        var insertedRow = Math.min(...selections.map(r => r.row), project.tasks.length);
        var taskData = createTaskDataList(rowCount, () => ({ name: "<新里程碑>", duration: 0 }));
        project.insertTasksByRow(insertedRow, taskData);
        ganttSheet.setSelection(insertedRow, -1, rowCount, -1);
    }

    function deleteTask() {
        var project = ganttSheet.project;
        var rowIds = getSelectedTaskNumbers();
        project.removeTasks(rowIds);
    }

    function indentTask() {
        var project = ganttSheet.project;
        var rowIds = getSelectedTaskNumbers();
        project.indentTasks(rowIds);
    }

    function outdentTask() {
        var project = ganttSheet.project;
        var rowIds = getSelectedTaskNumbers();
        project.outdentTasks(rowIds);
    }

    function linkTask() {
        var project = ganttSheet.project;
        var links = [];
        var selections = ganttSheet.getSelections();
        var previous = -1;
        for (var range of selections) {
            if (previous != -1) {
                links.push([previous, range.row]);
            }
            for (var row = range.row + 1; row < range.row + range.rowCount; row++) {
                links.push([row - 1, row]);
            }
            previous = range.row + range.rowCount - 1;
        }
        if (links.length <= 0) {
            return;
        }
        project.suspendSchedule();
        for (var link of links) {
            var [fromTaskNumber, toTaskNumber] = link;
            try {
                project.addDependency({ fromTaskNumber, toTaskNumber });
            } catch { }
        }
        project.resumeSchedule();
    }

5.日历

甘特图的这些新玩法,你都知道吗?_甘特图_06

(可在甘特图插件内实现日历内容的调整)

JavaScript代码:

/*REPLACE_MARKER*/
/*DO NOT DELETE THESE COMMENTS*/
var myTable;
var ganttSheet;
var roundBarsToWholeDays = true;

window.onload = function () {
    var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 0 });
    initSpread(spread);
    initSplitView(spread);
};

function initSpread(spread) {
    spread.suspendPaint();
    initDataSource(spread);
    initGanttSheet(spread);
    spread.resumePaint();
}

function initGanttSheet(spread) {
    ganttSheet = spread.addSheetTab(0, "GanttSheet", GC.Spread.Sheets.SheetType.ganttSheet);
    var view = myTable.addView("ganttView", [
        { value: "id", caption: "Id", width: 40 },
        { value: "taskNumber", caption: "NO.", width: 60 },
        { value: "name", caption: "Task Name", width: 200 },
        { value: "duration", caption: "Duration", width: 90 },
        { value: "predecessors", caption: "Predecessors", width: 120 }
    ]);
    view.fetch().then(function () {
        ganttSheet.bindGanttView(view);
    });
    initSidePanel(ganttSheet);
}

function initSidePanel(ganttSheet) {
    var addTaskItem = document.getElementById("add-task");
    var addSummayItem = document.getElementById("add-summary");
    var addMilestoneItem = document.getElementById("add-milestone");

    var deleteItem = document.getElementById("delete-task");

    var indentTaskItem = document.getElementById("indent-task");
    var outdentTaskItem = document.getElementById("outdent-task");

    var linkTaskItem = document.getElementById("link-task");
    var unlinkTaskItem = document.getElementById("unlink-task");

    var submitItem = document.getElementById("submit-changes");
    var cancelItem = document.getElementById("cancel-changes");

    addTaskItem.addEventListener("click", function () {
        ganttSheet.suspendPaint()
        addTask();
        ganttSheet.resumePaint();
    });
    addSummayItem.addEventListener("click", function () {
        ganttSheet.suspendPaint()
        addSummary();
        ganttSheet.resumePaint();
    });
    addMilestoneItem.addEventListener("click", function () {
        ganttSheet.suspendPaint()
        addMilestone();
        ganttSheet.resumePaint();
    });

    deleteItem.addEventListener("click", function () {
        ganttSheet.suspendPaint()
        deleteTask();
        ganttSheet.resumePaint();
    });

    indentTaskItem.addEventListener("click", function () {
        ganttSheet.suspendPaint()
        indentTask();
        ganttSheet.resumePaint();
    });
    outdentTaskItem.addEventListener("click", function () {
        ganttSheet.suspendPaint()
        outdentTask();
        ganttSheet.resumePaint();
    });

    linkTaskItem.addEventListener("click", function () {
        ganttSheet.suspendPaint()
        linkTask();
        ganttSheet.resumePaint();
    });
    unlinkTaskItem.addEventListener("click", function () {
        ganttSheet.suspendPaint()
        unlinkTask();
        ganttSheet.resumePaint();
    });

    submitItem.addEventListener("click", function () {
        ganttSheet.submitChanges();
    });
    cancelItem.addEventListener("click", function () {
        ganttSheet.cancelChanges();
    });

    function addTask() {
        var project = ganttSheet.project;
        var selections = ganttSheet.getSelections();
        var insertedRow = Math.min(...selections.map(r => r.row), project.tasks.length)
        var rowCount = selections.map(r => r.rowCount).reduce((pre, current) => { return pre + current });
        var taskData = createTaskDataList(rowCount, () => ({ name: "<新任务>" }));
        project.insertTasksByRow(insertedRow, taskData);
    }

    function addSummary() {
        var project = ganttSheet.project;
        var selectedRange = ganttSheet.getSelections()[0];
        var insertedRow = selectedRange.row;
        var insertedTaskNumbers = ganttSheet.getTaskByRow(insertedRow).taskNumber || project.count;
        var selectedTasks = getSelectedRowIndexes().map((row) => ganttSheet.getTaskByRow(row)).filter((row) => !!row);

        if (selectedTasks.length == 0) {
            project.insertTasks(insertedTaskNumbers, [{ name: "<新摘要任务>" }, { name: "<新任务>" }]);
            project.indentTasks(insertedTaskNumbers + 1);
        } else {
            project.insertTasks(insertedTaskNumbers, { name: "<新摘要任务>" }, selectedTasks[0].level);
            project.indentTasks(selectedTasks.map((t) => t.taskNumber));
        }
        ganttSheet.setSelection(insertedRow, -1, 1, -1);
    }

    function addMilestone() {
        var project = ganttSheet.project;
        var selections = ganttSheet.getSelections();
        var rowCount = selections.map(r => r.rowCount).reduce((pre, current) => { return pre + current });
        var insertedRow = Math.min(...selections.map(r => r.row), project.tasks.length);
        var taskData = createTaskDataList(rowCount, () => ({ name: "<新里程碑>", duration: 0 }));
        project.insertTasksByRow(insertedRow, taskData);
        ganttSheet.setSelection(insertedRow, -1, rowCount, -1);
    }

    function deleteTask() {
        var project = ganttSheet.project;
        var rowIds = getSelectedTaskNumbers();
        project.removeTasks(rowIds);
    }

    function indentTask() {
        var project = ganttSheet.project;
        var rowIds = getSelectedTaskNumbers();
        project.indentTasks(rowIds);
    }

    function outdentTask() {
        var project = ganttSheet.project;
        var rowIds = getSelectedTaskNumbers();
        project.outdentTasks(rowIds);
    }

    function linkTask() {
        var project = ganttSheet.project;
        var links = [];
        var selections = ganttSheet.getSelections();
        var previous = -1;
        for (var range of selections) {
            if (previous != -1) {
                links.push([previous, range.row]);
            }
            for (var row = range.row + 1; row < range.row + range.rowCount; row++) {
                links.push([row - 1, row]);
            }
            previous = range.row + range.rowCount - 1;
        }
        if (links.length <= 0) {
            return;
        }
        project.suspendSchedule();
        for (var link of links) {
            var [fromTaskNumber, toTaskNumber] = link;
            try {
                project.addDependency({ fromTaskNumber, toTaskNumber });
            } catch { }
        }
        project.resumeSchedule();
    }

    function unlinkTask() {
        var project = ganttSheet.project;
        var taskNumbers = getSelectedTaskNumbers();
        var dependencies = [];
        if (taskNumbers.length == 1) {
            var task = project.getTaskByRow(taskNumbers[0]);
            dependencies = [...task.predecessorDependencies, ...task.successorDependencies];
        } else {
            var taskNumberSet = {};
            for (var taskNumber of taskNumbers) {
                taskNumberSet[taskNumber] = true;
            }
            dependencies = project.dependencies.filter(dp => taskNumberSet[dp.from.taskNumber] && taskNumberSet[dp.to.taskNumber]);
        }
        if (dependencies.length >= 1) {
            project.removeDependency(dependencies);
        }
    }

    function getSelectedRowIndexes() {
        var rows = [];
        var selections = ganttSheet.getSelections();
        for (var range of selections) {
            for (var row = range.row; row < range.row + range.rowCount; row++) {
                rows.push(row);
            }
        }
        return rows;
    }

6.导入和导出操作

甘特图插件中展示的内容导出至PDF及Excel的格式。

甘特图的这些新玩法,你都知道吗?_甘特图_07

(支持导入导出能力)

JavaScript代码:

/*REPLACE_MARKER*/
/*DO NOT DELETE THESE COMMENTS*/
var myTable;
var ganttSheet;
var roundBarsToWholeDays = true;

window.onload = function() {
    var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 0 });
    initSpread(spread);
    initSplitView(spread);
};

function initSpread(spread) {
    spread.suspendPaint();
    initDataSource(spread);
    initGanttSheet(spread);
    spread.resumePaint();
}

function initDataSource(spread) {
    var tableName = "Gantt_Id";
    var baseApiUrl = getBaseApiUrl();
    var apiUrl = baseApiUrl + "/" + tableName;
    var dataManager = spread.dataManager();
    myTable = dataManager.addTable("myTable", {
        batch: true,
        remote: {
            read: {
                url: apiUrl
            }
        },
        schema: {
            hierarchy: {
                type: "Parent",
                column: "parentId"
            },
            columns: {
                id: { isPrimaryKey: true },
                taskNumber: { dataType: "rowOrder" }
            }
        }
    });
}

function initGanttSheet(spread) {
    ganttSheet = spread.addSheetTab(0, "GanttSheet", GC.Spread.Sheets.SheetType.ganttSheet);
    var view = myTable.addView("ganttView", [
        { value: "taskNumber", caption: "NO.", width: 60 },
        { value: "name", caption: "Task Name", width: 200 },
        { value: "duration", caption: "Duration", width: 90 },
        { value: "predecessors", caption: "Predecessors", width: 120, visible: false }
    ]);
    view.fetch().then(function() {
        ganttSheet.bindGanttView(view);
    });
    initSidePanel(spread, ganttSheet);
}

function initSidePanel(spread, ganttSheet) {
    var excelIo = new GC.Spread.Excel.IO();

    var fileInput = document.getElementById("file-input");
    var openFileItem = document.getElementById("open-file");
    var fileNameItem = document.getElementById("file-name");
    var exportJSONItem = document.getElementById("export-to-json");
    var exportSJSItem = document.getElementById("export-to-sjs");
    var exportExcelItem = document.getElementById("export-to-excel");
    var printItem = document.getElementById("print");
    var pdfItem = document.getElementById("pdf");

    var exportFileName = "export";

    openFileItem.addEventListener('click', function() {
        fileInput.click();
    });

    fileInput.addEventListener('change', function(e) {
        fileNameItem.value = 'Loading file...';
        var file = fileInput.files[0];
        if (!file) {
            alert("Upload a file first.");
            return;
        }
        var fileName = file.name;
        var suffix = fileName.substr(fileName.lastIndexOf('.'));
        if (suffix === '.xlsx' || suffix === '.xlsm') {
            // here is excel IO API
            excelIo.open(file, function(json) {
                spread.fromJSON(json);
                fileNameItem.value = fileName;
                fileInput.value = '';
            }, function(e) {
                // process error
                console.log(e);
            });
        } else if (suffix === '.ssjson' || suffix === '.json') {
            var reader = new FileReader();
            reader.onload = function() {
                var spreadJson = JSON.parse(this.result);
                spread.fromJSON(spreadJson);
                fileNameItem.value = fileName;
                fileInput.value = '';
            };
            reader.readAsText(file);
        } else if (suffix === '.sjs') {
            spread.open(file, () => {
                fileNameItem.value = fileName;
                fileInput.value = '';
            }, (e) => {
                console.log(e);
            }, {
                openMode: GC.Spread.Sheets.OpenMode.normal,
                fullRecalc: true,
            });
        }
    });

    exportJSONItem.addEventListener('click', function () {
        var fileName = exportFileName + ".ssjson";
        var json = spread.toJSON();
        saveAs(new Blob([JSON.stringify(json)], { type: "text/plain;charset=utf-8" }), fileName);
    });

    exportSJSItem.addEventListener('click', function () {
        var fileName = exportFileName + ".sjs";
        spread.save(function (blob) {
            saveAs(blob, fileName);
        }, function (e) {
            // process error
            console.log(e);
        }, {
            fileType: GC.Spread.Sheets.FileType.ssjson,
            includeBindingSource: true,
            saveAsView: true
        });
    });

    exportExcelItem.addEventListener('click', function () {
        var fileName = exportFileName + ".xlsx";
        var json = spread.toJSON({ includeBindingSource: true, saveAsView: true });
        // here is excel IO API
        excelIo.save(json, function(blob) {
            saveAs(blob, fileName);
        }, function(e) {
            // process error
            console.log(e);
        }, { xlsxStrictMode: false });
    });

    printItem.addEventListener('click', function() {
        spread.print();
    });

    pdfItem.addEventListener('click', function() {
        spread.savePDF(function (blob) {
            var url = URL.createObjectURL(blob);
            pwin = window.open(url);
        });
    });
}

总结

甘特图是一种强大的项目管理工具,通过直观的时间轴展示任务的安排和进度。它能帮助项目经理们创建详细的项目计划,有效跟踪进度,并合理分配资源。甘特图还可以管理任务间的依赖关系,及时调整时间表,并识别风险与关键路径。它在项目管理中扮演着重要的角色,提高了团队的协作效率和项目的成功率。通过使用甘特图,项目团队能够更好地掌握项目进展,作出决策,并确保项目按时交付。

如果您对该插件感兴趣,可以访问葡萄城官网下载SpreadJS产品。



作者:葡萄城技术开发团队


标签:function,ganttSheet,玩法,甘特图,project,getElementById,spread,var,知道
From: https://blog.51cto.com/powertoolsteam/8390067

相关文章

  • 采购CRM系统,这些费用你知道吗?
    近些年CRM软件市场规模高速发展,技术商数量和用户数都突飞猛进。市面上产品种类丰富,系统的价格也是差距很大,从几百块到几十万不等,尽管很多厂商的价格是公开的但部署CRM之后成本很快超出了预期,实施CRM系统都有哪些费用?我们以SaaS模式为例1.产品基本费用SaaS模式能够很大的节省企......
  • 10个PPT冷门技巧,你都知道几个?@弎十二
    01 取色器外部取色相信对于用过PPT的小伙伴来说,取色器是一个比较熟悉的功能。在颜色填充面板中通过这个功能,常规上是可以吸取画布内所有的颜色的,比如这样:但是,痛点来了:当需要吸取外部的颜色,以往就需要截图插入到PPT当中才能进行取色,一旦需要的颜色多起来,操作就会变得很繁......
  • 网络二层环路,都是这么排查的!你都知道吗?
    1、判断网络二层环路当网络业务不可用、设备指示灯有规律的一起闪烁、登录设备出现卡顿等现象时,表明网络中可能存在二层环路。网络中是否存在二层环路有以下几种方式进行确认:方法一:通过查看端口流量发现环路风暴,判断环路。在设备上执行命令:displayinterfacebrief|includeup通......
  • 铺先生:转店中有什么坑要知道的?这三个要注意了
    转店中有什么坑要知道的?接手转店这件事,对于很多朋友来说,可能认为只要签了合同之后就可以了,但是其实在这件事中,有很多问题需要注意的,否则是很容易踩到陷阱的。那么转店中有什么坑需要注意的呢?下面就让小编来跟大家说一下吧。1. 转让原因转店老板是因为什么原因才选择的转店?这个问题......
  • 我敢打赌,这个架构你一定知道!
    大家好,我是鱼皮。开发后端项目时,我们最常见的一种架构模式就是分层架构。所谓的分层架构,就是把系统自上而下分为多个不同的层,每一层都有特定的功能和职责,且只和自己的直接上层与直接下层“打交道”。分层架构的优点是:每一层都有明确定义的职责,易于理解和维护;而且各层可以独立扩......
  • 知道CountDownLatch是做什么的,那你知道它的底层是如何实现的吗?
    一、概述CountDownLatch是一个多线程控制工具,用来控制线程的等待。设置需要countDown的数量num,然后每一个线程执行完毕后,调用countDown()方法,而主线程调用await()方法执行等待,直到num个子线程执行了countDown()方法,则主线程解除阻塞,开始继续执行。其具体操作流程类似火箭发射,我们......
  • 【周末闲谈】关于“数据库”你又知道多少?
    个人主页:【......
  • 你不知道的CSS骚操作
    1.禁用鼠标事件、移动端禁止图片长按保存功能(PC端禁止鼠标点击事件,移动端禁止触摸事件还有长按事件).no-events{pointer-events:none}2.移动端禁止用户长按文字选择功能.unselect{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:......
  • 学Android不知道这些,毕业=失业!
    很多专科毕业,Android不好找工作的同学,看过来!!这样一个竞争激烈的市场环境下,想要成为一名优秀的Android开发者,仅仅依靠课本上的知识是远远不够的。那么,作为一名Android开发学习者,有哪些知识是我们必须掌握的呢?1.掌握扎实的基本功俗话说:基础不牢,地动山摇。作为应届生,由于没有什么实际......
  • 要是早知道秋招是这么回事就好了!
    本文首发自公粽hao「林行学长」,欢迎来撩,免费领取20个求职工具资源包。了解校招、分享校招知识的学长来了!经过了一个秋招,相信不少同学都有一种体会:要是早知道秋招这么多信息就好了!01.秋招分批次招聘首先,秋季招聘通常会分为多个批次进行。一般而言,第一批次的招聘会集中在八月初开始,......