All versions of this documentation
X

Excel

This example shows how to transform a XLSX file into a Ogma's network visualization. The dataset contains an XLSX spreadsheet file with 2 tabs: "nodes" and "edges". The network data for character relationships within George R. R. Martin's A Storm of Swords, the third novel in his series A Song of Ice and Fire (also known as the HBO television adaptation Game of Thrones). This data was originally compiled by A. Beveridge and J. Shan, "Network of Thrones," Math Horizons Magazine , Vol. 23, No. 4 (2016), pp. 18-22.. The SheetJS Community Edition is used to correctly parse the XLSX file.

Open in a new window.
          <!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <script src="../build/ogma.min.js"></script>
    <link href="fonts/font-awesome/css/font-awesome.min.css" rel="stylesheet">
    <script src="https://unpkg.com/xlsx@0.11.12/dist/xlsx.core.min.js"></script>
    <style>
        #graph-container {
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            position: absolute;
            margin: 0;
            overflow: hidden;
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            -o-user-select: none;
            user-select: none;
        }

        .toolbar {
            display: block;
            position: absolute;
            top: 20px;
            right: 20px;
            padding: 10px;
            box-shadow: 0 1px 5px rgba(0, 0, 0, 0.65);
            border-radius: 4px;
            background: #ffffff;
            color: #222222;
            font-weight: 300;
            max-width: 350px;
        }

        .controls {
            text-align: center;
            margin-top: 5px;
        }

        .btn {
            padding: 6px 8px;
            background-color: white;
            cursor: pointer;
            font-size: 18px;
            border: none;
            border-radius: 5px;
            outline: none;
        }

        .btn:hover {
            color: #333;
            background-color: #e6e6e6;
        }

        .menu {
            border: 1px solid #ddd;
            width: 80%;
            font-size: 14px;
            margin-top: 10px;
        }
    </style>
</head>

<body>
    <div id="graph-container"></div>
    <div class="toolbar">
        <div class="controls">
            <button id="load-xlsx" class="btn menu">click to load XLSX</button>
        </div>
    </div>

    <script>
        'use strict';

        var ogma = new Ogma({
            container: 'graph-container',
        });

        // some UI logic

        function layout() {
            return ogma.layouts.force({
                locate: { padding: 80 },
            });
        }


        // Add some edge styling rules
        ogma.styles.addEdgeRule({
            color: function (e) {
                return '#80ce87';
            },
            shape: "arrow",
            width: function (e) {
                return Math.log(e.getData("weight"));
            }
        });

        // Add some node styling rules
        ogma.styles.addNodeRule({
            text: {
                content: function (n) {
                    return n.getData("label");
                },
                minVisibleSize: 2
            },
            radius: function (n) {
                return n.getDegree();
            },
            icon: {
                content: function (n) {
                    return "\uf2c0";
                },
                font: 'FontAwesome',
                color: 'rgb(61,139,223)',
                minVisibleSize: 0
            },
            outerStroke: {
                color: 'rgb(61,139,223)',
                width: 2
            },
            color: 'white'
        });

        // this is a utility function help scan the sheet
        function forEachRecord(sheet, cb) {
            // Sheet.js puts a special property !ref that contains the range of the data in the sheet
            // here we pick its value (i.e. A1:B108), get the value after the : and get the final numeric value ( "108") 
            var rows = + workbook.Sheets[sheet]['!ref'].split(':')[1].substring(1);
            // var columns = 
        }

        function toRawGraph(workbook) {
            // format the incoming workbook object to the RawGraph format
            // we know there are two tabs in the workbook: "nodes" and "edges" but in case Sheet.js provides a list of them

            // Luckily there's a utility function to help iterate throught the sheets records
            var nodes = XLSX.utils.sheet_to_json(workbook.Sheets.nodes).map(function (record) {
                return { id: record.id, data: { label: record.label } };
            });
            var edges = XLSX.utils.sheet_to_json(workbook.Sheets.edges).map(function (record, row) {
                return {
                    id: record.source + "-" + record.target + "-" + row,
                    source: record.source,
                    target: record.target,
                    data: { weight: record.weight }
                };
            });

            return ogma.setGraph({ nodes: nodes, edges: edges }).then(layout);
        }

        document.querySelector('#load-xlsx').addEventListener('click', function (evt) {
            // load the xlsx from the URL and parse it returning a JSON
            return fetch('files/got.xlsx')
                .then(function (res) {
                    /* get the data as a Blob */
                    if (!res.ok) throw new Error("fetch failed");
                    return res.arrayBuffer();
                }).then(function (ab) {
                    /* parse the data when it is received */
                    var data = new Uint8Array(ab);
                    var workbook = XLSX.read(data, { type: "array" });

                    toRawGraph(workbook);
                });
        });

    </script>
</body>

</html>