如何使用JavaScript将2D数组JSON属性放入Excel文件新列中

sauutmhj  于 4个月前  发布在  Java
关注(0)|答案(1)|浏览(76)

我需要用JavaScript创建一个Web应用程序来将JSON文件转换为Excel文件,以这种方式:JSON文件包含一些简单的属性,每个值都应该放在Excel文件的列中,也有一些2D数组或嵌套,嵌套的JSON属性,我想在Excel文件中为JSON文件中的父属性的孩子添加额外的列或行。

"name": "processingPriority",

      "type": [

        "null",

        "string"

      ],

      "doc": "",

      "default": null,

      "since": "1.0"

    },

    {

      "name": "flags",

      "type": [

        "null",

        {

          "type": "array",

          "items": "string",

          "java-class": "java.util.List"

        }

      ],

      "doc": "Mandatory. Empty list allowed, see below for allowed values, List of <<TransactionFlags, allowed ENUM values>>",

      "default": null,

      "since": "1.0"

    },

    {

      "name": "customerData",

      "type": [

        "null",

        "string"

      ],

      "doc": "",

      "default": null,

      "since": "1.0"

    },

    {

      "name": "account",

      "type": [

        "null",

        {

          "type": "record",

          "name": "TransactionAccount",

          "fields": [

            {

              "name": "id",

              "type": [

                "null",

                "string"

              ],

              "doc": "Mandatory. Unique ID (needs to match the one used by WebAPI)",

              "default": null,

              "since": "1.0"

            },

字符串
使用下面的函数,我可以生成这样的Excel文件:excel file

// ... my existing code

function downloadAsExcel() {
    // ... my existing code

    function getTypeAsString(type, parentName = '') {
        if (Array.isArray(type)) {
            return type.map(t => getTypeAsString(t)).join(', ');
        } else if (typeof type === 'object' && type !== null) {
            if (type.type === 'record' && Array.isArray(type.fields)) {
                const fields = type.fields.map(field => {
                    const fieldName = field.name;
                    const fieldComments = field.doc ? ` (${field.doc})` : '';
                    return `${parentName}.${fieldName}${fieldComments}:${getTypeAsString(field.type, `${parentName}.${fieldName}`)}`;
                }).join(', ');
                return `{${fields}}`;
            } else {
                const objKeys = Object.keys(type).map(key => {
                    if (typeof type[key] === 'object' && type[key] !== null) {
                        return `${key}:${getTypeAsString(type[key], `${parentName}.${key}`)}`;
                    } else {
                        return `${key}:${type[key]}`;
                    }
                }).join(', ');
                return `{${objKeys}}`;
            }
        } else {
            return typeof type === 'undefined' ? 'null' : type.toString();
        }
    }

    function processNestedAttributes(fields, nestedLevel = 0, parentName = '') {
        let nestedRows = [];

        fields.forEach(field => {
            const typeValue = getTypeAsString(field.type, `${parentName}.${field.name}`);

            if (typeof field.type === 'object' && field.type !== null && field.type.type === 'record' && Array.isArray(field.type.fields)) {
                field.type = `{Nested Table}`;
                nestedRows.push([field.name, 'null', typeValue, field.doc, field.default, field.since, nestedLevel]);
                const nestedFieldRows = processNestedAttributes(field.type.fields, nestedLevel + 1, `${parentName}.${field.name}`);
                nestedRows = nestedRows.concat(nestedFieldRows);
            } else {
                if (typeValue === 'null') {
                    nestedRows.push([field.name, typeValue, '', field.doc, field.default, field.since, nestedLevel]);
                } else {
                    nestedRows.push([field.name, 'other', typeValue, field.doc, field.default, field.since, nestedLevel]);
                }
            }
        });

        return nestedRows;
    }

    for (var i = 0; i < jsonContent.fields.length; i++) {
        const field = jsonContent.fields[i];

        if (typeof field.type === 'object' && field.type !== null && field.type.type === 'record' && Array.isArray(field.type.fields)) {
            field.type = `{Nested Table}`;
            dataRows.push([field.name, 'null', getTypeAsString(field.type), field.doc, field.default, field.since, 0]);
            const nestedRows = processNestedAttributes(field.type.fields, 1, field.name);
            dataRows = dataRows.concat(nestedRows);
        } else {
            const typeValue = getTypeAsString(field.type);
            if (typeValue === 'null') {
                dataRows.push([field.name, typeValue, '', field.doc, field.default, field.since, 0]);
            } else {
                dataRows.push([field.name, 'other', typeValue, field.doc, field.default, field.since, 0]);
            }
        }
    }

    // ... my existing code
}
// ... my existing code


但我想有一个新的列嵌套属性值在类型列.我怎么能改变代码有这样的Excel文件?

dgtucam1

dgtucam11#

我喜欢分裂逻辑..

function demo(json) {
  var it = new JIterator(json);
  var lastLevel = it.BreadthFirst();
  var csvCollection = {};
  do {
    if (it.Level == 1) {
      var val = (it.Current.HasSimpleValue) ? it.Value : JSON.stringify(eval('json' + it.Path)); // a bit dirty trick as there is missing full JSON in JIterator
      if (!csvCollection[it.Key]) csvCollection[it.Key] = [];
      csvCollection[it.Key].push(val);
    }
  } while (lastLevel = it.BreadthFirst());
  /* Transposited temporary data: {
  "name":["processingPriority","flags","customerData","account"],
  "type":["['null','string']","['null',{'type':'array','items':'string','java-class':'java.util.List'}]","['null','string']","['null',{'type':'record','name':'TransactionAccount','fields':[{'name':'id','type':['null','string'],'doc':'Mandatory. Unique ID (needs to match the one used by WebAPI)','default':null,'since':'1.0'}]}]"],
  "doc":["","Mandatory. Empty list allowed, see below for allowed values, List of <<TransactionFlags, allowed ENUM values>>",""],
  "default":["null","null","null"],
  "since":["1.0","1.0","1.0"]}*/
  var head = Object.keys(csvCollection);
  var csv = [head.join('\t')];
  var rowNo = 0, maxRows = 0;
  do {
    var row = [];
    for (var col = 0; col < head.length; col++) {
      row.push(csvCollection[head[col]][rowNo]);
      if (csvCollection[head[col]][rowNo]) {
        if (maxRows < csvCollection[head[col]].length) maxRows = csvCollection[head[col]].length;
      }
    }
    csv.push(row.join('\t'));
    rowNo++;
  } while (rowNo < maxRows);
  csv = csv.join('\n');
  prompt("CSV:", csv);
}

// https://github.com/eltomjan/ETEhomeTools/blob/master/HTM_HTA/JSON_Iterator_IIFE.js
var JNode = (function(jsNode) {
  function JNode(_json, _parent, _pred, _key, _value) {
    this.parent = _parent;
    this.pred = _pred;
    this.node = null;
    this.next = null;
    this.key = _key;
    this.value = _value;
    this.json = _json;
  }
  JNode.prototype = {
    get HasOwnKey() {
      return this.key && (this.key.constructor !== Number);
    },
    get HasStringValue() {
      return this.value.constructor === String;
    },
    get HasSimpleValue() {
      return this.value !== null &&
        !(this.value instanceof Array) &&
        !(this.value instanceof Object)
    }
  };
  return JNode;
})();
var JIterator = (function(json) {
  var JNodePrivates = (function(parent) {
    function JNodePrivates() {
      this.root = null;
      this.current = null;
    }
    JNodePrivates.prototype = {
      get Root() {
        return this.root;
      },
      setRoot: function(newRoot) {
        return (this.root = newRoot);
      },
      get Current() {
        return this.current;
      },
      setCurrent: function(newCurrent) {
        return (this.current = newCurrent);
      }
    };
    return JNodePrivates;
  })();
  var maxLevel = -1;

  function JIterator(json, parent) {
    if (this._privates === undefined) this._privates = new JNodePrivates();
    if (parent === undefined) parent = null;
    var pred = null,
      localCurrent;
    for (var child in json) {
      var obj = json[child] instanceof Object;
      if (json instanceof Array) child = parseInt(child); // non-associative array
      if (!this._privates.Root) this._privates.setRoot(localCurrent = new JNode(json, parent, null, child, json[child]));
      else {
        localCurrent = new JNode(json[child], parent, pred, child, obj ? ((json[child] instanceof Array) ? [] : {}) : json[child]);
      }
      if (pred) pred.next = localCurrent;
      if (parent && parent.node == null) parent.node = localCurrent;
      pred = localCurrent;
      if (obj) {
        var memPred = pred;
        JIterator.call(this, json[child], pred);
        pred = memPred;
      }
    }
    if (!this._privates.Current && this._privates.Root) this._privates.setCurrent(this._privates.Root);
    this.Level = 0;
  }
  JIterator.prototype = {
    // Public Getters
    get Current() {
      return this._privates.Current;
    },
    SetCurrent: function(newCurrent) {
      return this._privates.setCurrent(newCurrent);
    },
    get Path() {
      var steps = [],
        level = this._privates.Current;
      do {
        if (level != null && level.value instanceof Object) {
          if (level.value instanceof Array) {
            if (steps.length > 0) {
              steps.push(level.key + '[' + steps.pop() + ']');
            } else {
              steps.push(level.key);
            }
          } else {
            steps.push(level.key);
          }
        } else {
          if (level != null) steps.push(level.key);
          else break;
        }
        level = level.parent;
      } while (level != null);
      steps.forEach(function(el, i) {
        if (!isNaN(el)) steps[i] = '[' + el + ']';
      });
      return steps.reverse().join('.');
    },
    // Public Setters
    set current(value) {
      console.log('Use SetCurrent(' + value + ') !');
      throw 'Access to current Denied !';
    },
    // Public methods
    Parent: function() {
      var retVal = this._privates.Current.parent;
      if (retVal == null) return false;
      this.Level--;
      return this._privates.setCurrent(retVal);
    },
    Pred: function() {
      var retVal = this._privates.Current.pred;
      if (retVal == null) return false;
      return this._privates.setCurrent(retVal);
    },
    Node: function() {
      var retVal = this._privates.Current.node;
      if (retVal == null) return false;
      this.Level++;
      return this._privates.setCurrent(retVal);
    },
    Next: function() {
      var retVal = this._privates.Current.next;
      if (retVal == null) return false;
      return this._privates.setCurrent(retVal);
    },
    get Key() {
      if (this._privates.Current) return this._privates.Current.key;
      return undefined;
    },
    KeyDots: function() {
      return (!this.HasOwnKey) ? '' : (this._privates.Current.key + ':');
    },
    get Value() {
      if (this._privates.Current) return this._privates.Current.value;
      return undefined;
    },
    Reset: function() {
      this._privates.setCurrent(this._privates.Root);
      this.Level = 0;
    },
    RawPath: function() {
      var steps = [],
        level = this._privates.Current;
      do {
        if (level != null && level.value instanceof Object) {
          steps.push(level.key + (level.value instanceof Array ? '[]' : '{}'));
        } else {
          if (level != null) steps.push(level.key);
          else break;
        }
        level = level.parent;
      } while (level != null);
      var retVal = '';
      retVal = steps.reverse();
      return retVal;
    },
    DepthFirst: function() {
      if (this._privates.Current == null) return 0; // exit sign
      if (this._privates.Current.node != null) {
        this._privates.setCurrent(this._privates.Current.node);
        this.Level++;
        if (maxLevel < this.Level) maxLevel = this.Level;
        return 1; // moved down
      } else if (this._privates.Current.next != null) {
        this._privates.setCurrent(this._privates.Current.next);
        return 2; // moved right
      } else {
        while (this._privates.Current != null) {
          if (this._privates.Current.next != null) {
            this._privates.setCurrent(this._privates.Current.next);
            return 3; // returned up & moved next
          }
          this.Level--;
          this._privates.setCurrent(this._privates.Current.parent);
        }
      }
      return 0; // exit sign
    },
    BreadthFirst: function() {
      if (this._privates.Current == null) return 0; // exit sign
      if (this._privates.Current.next) {
        this._privates.setCurrent(this._privates.Current.next);
        return 1; // moved right
      } else if (this._privates.Current.parent) {
        var level = this.Level;
        while (this.DepthFirst() && level !== this.Level);
        if (this._privates.Current) return 2; // returned up & moved next
        do {
          this.Reset();
          level++;
          while (this.DepthFirst() && level !== this.Level);
          if (this._privates.Current) return 3; // returned up & moved next
        } while (maxLevel >= level);
        return this._privates.Current != null ? 3 : 0;
      } else if (this._privates.Current.node) {
        this._privates.setCurrent(this._privates.Current.node);
        return 3;
      } else if (this._privates.Current.pred) {
        while (this._privates.Current.pred) this._privates.setCurrent(this._privates.Current.pred);
        while (this._privates.Current && !this._privates.Current.node) this._privates.setCurrent(this._privates.Current.next);
        if (!this._privates.Current) return null;
        else return this.DepthFirst();
      }
    },
    ReadArray: function() {
      var retVal = {};
      var item = this._privates.Current;
      do {
        if (item.value instanceof Object) {
          if (item.value.length === 0) retVal[item.key] = item.node;
          else retVal[item.key] = item;
        } else retVal[item.key] = item.value;
        item = item.next;
      } while (item != null);
      return retVal;
    },
    FindKey: function(key) {
      var pos = this._privates.Current;
      while (this._privates.Current && this._privates.Current.key !== key) {
        if (!this.DepthFirst()) {
          this._privates.setCurrent(pos);
          return null;
        }
      }
      if (this._privates.Current.key === key) {
        var retVal = this._privates.Current;
        this._privates.setCurrent(pos);
        return retVal;
      } else {
        this._privates.setCurrent(pos);
        return null;
      }
    },
    FindValue: function(val) {
      var pos = this._privates.Current;
      while (this._privates.Current && this._privates.Current.value !== val) this.DepthFirst();
      if (this._privates.Current.value === val) {
        var retVal = this._privates.Current;
        this._privates.setCurrent(pos);
        return retVal;
      } else {
        this._privates.setCurrent(pos);
        return null;
      }
    },
    FindPair: function(key, value, move2) {
      var pos = this._privates.current;
      while (this._privates.current) {
        if (this._privates.current.key === key && this._privates.current.value === value) {
          break;
        } else this.DepthFirst();
      }
      if (move2) return this._privates.current;
      var retVal = this._privates.current;
      this.SetCurrent(pos);
      return retVal;
    },
    // Debug info methods
    PathDetails: function(brief) {
      var steps = [],
        level = this._privates.Current;
      do {
        if (level != null && level.value instanceof Object) {
          var size = 0;
          var items = level.node;
          if (!level.HasOwnKey && !brief) steps.push('[' + level.key + ']');
          else {
            if (brief) {
              if (level.HasOwnKey) steps.push(level.key);
            } else {
              while (items) {
                size++;
                items = items.next;
              }
              var type = (level.value instanceof Array ? '[]' : '{}');
              var prev = steps[steps.length - 1];
              if (prev && prev[0] === '[') {
                var last = prev.length - 1;
                if (prev[last] === ']') {
                  last--;
                  if (!isNaN(prev.substr(1, last))) {
                    steps.pop();
                    size += '.' + prev.substr(1, last);
                  }
                }
              }
              steps.push(level.key + type[0] + size + type[1]);
            }
          }
        } else {
          if (level != null) {
            if (!level.HasOwnKey) steps.push('[' + level.key + ']');
            else steps.push(level.key);
          } else break;
        }
        level = level.parent;
      } while (level != null);
      var retVal = "";
      retVal = steps.reverse();
      return retVal;
    },
    Move2path: function(json) {
      var nd = this._privates.current;
      var pth = [nd];
      while (nd.parent) {
        nd = nd.parent;
        pth.push(nd);
      }
      pth.reverse();
      for (var x in pth) json = json[pth[x].key];
      return json;
    },
    CreateNode: function(json, key, value) {
      var current = this._privates.Current;
      if (current) {
        current.node = new JNode(json, current, current.pred, key, value);
        if (isNaN(key)) json[key] = value;
        return current.node;
      } else {
        current = new JNode(json, null, null, key, value);
        json[key] = value;
        this._privates.setCurrent(current);
        this._privates.setRoot(current);
        return current;
      }
    }
  };
  return JIterator;
})();

demo([{
    "name": "processingPriority",
    "type": [
      "null",
      "string"
    ],
    "doc": "",
    "default": null,
    "since": "1.0"
  },
  {
    "name": "flags",
    "type": [
      "null",
      {
        "type": "array",
        "items": "string",
        "java-class": "java.util.List"
      }
    ],
    "doc": "Mandatory. Empty list allowed, see below for allowed values, List of <<TransactionFlags, allowed ENUM values>>",
    "default": null,
    "since": "1.0"
  },
  {
    "name": "customerData",
    "type": [
      "null",
      "string"
    ],
    "doc": "",
    "default": null,
    "since": "1.0"
  },
  {
    "name": "account",
    "type": [
      "null",
      {
        "type": "record",
        "name": "TransactionAccount",
        "fields": [{
          "name": "id",
          "type": [
            "null",
            "string"
          ],
          "doc": "Mandatory. Unique ID (needs to match the one used by WebAPI)",
          "default": null,
          "since": "1.0"
        }]
      }
    ]
  }
])

字符串

相关问题