JSON в Excel в JavaScript

Я пытаюсь сохранить данные в json, чтобы преуспеть в файле .xlsx. Json выглядит так (с изменением имен значений, это просто пример):

{"hum_in":[{"ts":1646034284215,"value":"22"},{"ts":1646033983313,"value":"22"}]}

Я попытался преобразовать и загрузить, используя этот код:

const EXCEL_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8';
const EXCEL_EXTENSION = '.xlsx';

function downloadAsExcel(data) {
    const worksheet = XLSX.utils.json_to_sheet(data);
    const workbook = {
        Sheets: {
            'data': worksheet
        },
        SheetNames: ['data']
    };
    const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
    console.info(excelBuffer);
    saveAsExcel(excelBuffer);
}

function saveAsExcel(buffer) {
    const data = new Blob([buffer], { type: EXCEL_TYPE });
    saveAs(data, "Export_" + new Date().getTime() + EXCEL_EXTENSION);
}

а затем вызывая это так:

downloadAsExcel(json);

Он вернул ошибку:

TypeError: r.forEach is not a function
    at rb (xlsx.full.min.js:23:18346)
    at Object.tb [as json_to_sheet] (xlsx.full.min.js:23:19000)
    at downloadAsExcel (app.js:233:34)
    at app.js:112:25

Кто-нибудь знает, что пошло не так?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Функция json_to_sheet принимает массив, тогда как ваш аргумент data является объектом. Вместо этого передайте ему свойство hum_in, чтобы настроить таргетинг на внутренний массив данных:

const worksheet = XLSX.utils.json_to_sheet(data.hum_in);

Вот более полный пример, включающий поддержку нескольких ключей в объекте данных:

const data = {"hum_in":[
  {"ts":1646034284215,"value":"22"},
  {"ts":1646033983313,"value":"22"}
]};

function generateAsExcel(data) {
  try {
    const workbook = XLSX.utils.book_new();
    
    for (let key in data) {
      const worksheet = XLSX.utils.json_to_sheet(data[key]);
      XLSX.utils.book_append_sheet(workbook, worksheet, key);
    }
    
    let res = XLSX.write(workbook, { type: "array" });
    console.info(`${res.byteLength} bytes generated`);
  } catch (err) {
    console.info("Error:", err);
  }
}

document.getElementById("gen").addEventListener("click",
  () => generateAsExcel(data));
<script type = "text/javascript" src = "//cdn.jsdelivr.net/npm/xlsx/dist/xlsx.full.min.js"></script>
<button id = "gen">Generate</button>

Чтобы объединить все ключи data в набор данных для создания одного рабочего листа, вы можете использовать что-то вроде этого:

const data = {
  "hum_in":[ {"ts":1646034284215,"value":"22"}, {"ts":1646033983313,"value":"22"} ],
  "wind_dir":[ {"ts":1646034284215,"value":"123"}, {"ts":1646033983313,"value":"125"} ]
};

let merged = Object.keys(data).reduce((merged, key) => {
  for (record of data[key]) { merged.push(Object.assign({ key }, record)); }
  return merged;
}, []);

console.info(merged);

Я не могу добавить свойство hum_in, потому что это свойство всегда меняется в зависимости от того, что клиент хочет экспортировать (один раз это hum_in, в следующий раз это wind_dir и так далее). Есть ли способ сделать это без точного свойства?

Deesak 22.03.2022 13:18

Пример с добавленной поддержкой нескольких ключей, каждый ключ в объекте data будет экспортирован на новый лист

Mike D Sutton 22.03.2022 13:35

Спасибо, работает хорошо! Можно ли разместить все ключи только на одном листе?

Deesak 22.03.2022 14:34

Добавлен дополнительный пример объединения наборов данных.

Mike D Sutton 22.03.2022 15:02

Большое спасибо! Есть ли какая-то документация на все это? Я пытался найти его, но, возможно, я не так искал.

Deesak 23.03.2022 09:25

Документы SheetJS доступны здесь, там много примеров

Mike D Sutton 23.03.2022 10:08

Другие вопросы по теме