Как сохранить значения массива в одном столбце при конвертации в CSV - PullRequest
0 голосов
/ 01 апреля 2020

Я пытаюсь преобразовать значения объекта в CSV, но метод join разделяет значения моего массива на разные столбцы в Excel. Любая идея о том, как я могу избежать этого?

Функция:


window.downloadCsv = function(records) {

    console.log(records);

    const array = [Object.keys(records)].concat(records);

    console.log(array);

    let result = array.map(it => {

        let objectValues = Object.values(it);
        for (let i = 0; i < objectValues.length; i++) {
            if (Array.isArray(objectValues[i])) {
                //Keep it as array
            }
        }

        return objectValues;
    }).join('\n');

    console.log(result);

    let hiddenElement = document.createElement('a');
    hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(result);
    hiddenElement.target = '_blank';
    hiddenElement.download = 'records.csv';
    hiddenElement.click();

};

Возможные записи ввода:

id: "5e8468e2db05ff589ca61b30"
title: "Example Application Number 1"
status: "Preparing Documents"
principalInvestigator: "Mr. Harry Styles"
coInvestigators: ["Niall Horan, Liam Payne, Zayn Malik, Louis Tomilson"]
partners: null
funder: "EPSRC Standard research"
researchGroup: "MedEng"
scheme: "Travel Grant"
requestedAmount: null
estimatedAmount: 1234
submissionDate: "2020-03-23T00:00:00.000+01:00"
startDate: "2020-03-29T00:00:00.000+01:00"
estimatedDuration: null
endDate: null
facility: null
comments: null
dateCreated: "2020-04-01T12:11:46.783+02:00"
lastUpdated: "2020-04-01T12:11:46.783+02:00"
dateDeleted: null
__proto__: Object

Текущий вывод результата:

id,title,status,principalInvestigator,coInvestigators,partners,funder,researchGroup,scheme
5e8468e2db05ff589ca61b30,Example Application Number 1,Preparing Documents,Mr. Harry Styles,Niall Horan, Liam Payne, Zayn Malik, Louis Tomilson

Желаемый вывод:

id,title,status,principalInvestigator,coInvestigators,partners,funder,researchGroup,scheme
5e8468e2db05ff589ca61b30,Example Application Number 1,Preparing Documents,Mr. Harry Styles,[Niall Horan, Liam Payne, Zayn Malik, Louis Tomilson],Apple,Microsoft,XresearchGroup,YScheme

Возможно, это легче понять в формате Excel. В настоящее время это выглядит после экспорта: https://imgur.com/2I8h9kl

И желаемый вид будет: https://imgur.com/bFUKQY2

Итак, в значительной степени Я хотел бы сохранить значения массивов в одном столбце, а не разделять их на разные столбцы, что также сдвигает все остальные столбцы в CSV.

Ответы [ 3 ]

1 голос
/ 01 апреля 2020

Старайтесь всегда создавать минимальный воспроизводимый пример ({ ссылка })

Вот мое:

Самая важная часть такова:

const headers = Object.keys(records).join(',')
const values = Object.values(records).map(child => {
    if (child instanceof Array){
      //return child.join('; ');
      const str = JSON.stringify(child).replace(/"/g, "'");
      return `"${str}"`;
    }else{
      return child;
    }

}).join(',')

const result = [headers, values].join('\n')

Где мы берем ключи и значение и помещаем их каждый в массив, а затем помещаем их в один массив и соединяем их новой строкой [headers, values].join('\n')

Внутри карты вы можете сделать либо this:

const values = Object.values(records).map(child => {
    if (child instanceof Array){
      const str = JSON.stringify(child).replace(/"/g, "'");
      return `"${str}"`;
    }else{
      return child;
    }

}).join(',')

, что заставляет строку массива отображаться в Excel следующим образом:

"['Niall Horan','Liam Payne','Zayn Malik','Louis Tomilson']"

Или вы можете сделать карту следующим образом:

const values = Object.values(records).map(child => {
    if (child instanceof Array){
      return child.join('; ');
    }else{
      return child;
    }

}).join(',')

И затем вывод в Excel выглядит следующим образом (точка с запятой не читается как разделитель столбцов, если вы не используете этот языковой стандарт, то есть немецкий язык):

"Niall Horan; Liam Payne; Zayn Malik; Louis Tomilson"

const recordObj = {
  id: "5e8468e2db05ff589ca61b30",
  title: "Example Application Number 1",
  status: "Preparing Documents",
  principalInvestigator: "Mr. Harry Styles",
  coInvestigators: ["Niall Horan", "Liam Payne", "Zayn Malik", "Louis Tomilson"],
  partners: null,
  funder: "EPSRC Standard research",
  researchGroup: "MedEng",
  scheme: "Travel Grant",
  requestedAmount: null,
  estimatedAmount: 1234,
  submissionDate: "2020-03-23T00:00:00.000+01:00",
  startDate: "2020-03-29T00:00:00.000+01:00",
  estimatedDuration: null,
  endDate: null,
  facility: null,
  comments: null,
  dateCreated: "2020-04-01T12:11:46.783+02:00",
  lastUpdated: "2020-04-01T12:11:46.783+02:00",
  dateDeleted: null
}

downloadCsv(recordObj)

function downloadCsv(records) {

    //console.log(records);
    const headers = Object.keys(records).join(',')
    const values = Object.values(records).map(child => {
        if (child instanceof Array){
          //return child.join('; ');
          const str = JSON.stringify(child).replace(/"/g, "'");
          return `"${str}"`;
        }else{
          return child;
        }
        
    }).join(',')
    
    const result = [headers, values].join('\n')
    //console.log(headers);
    //console.log(values);
    console.log(result);

    let hiddenElement = document.createElement('a');
    hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(result);
    hiddenElement.target = '_blank';
    hiddenElement.download = 'records.csv';
    hiddenElement.click();

}
.as-console-wrapper { max-height: 100% !important; top: 0; }
1 голос
/ 01 апреля 2020

Попробуйте преобразовать массив в строку, а затем заменить запятые другим разделителем, например точкой с запятой - таким образом интерпретатор csv не будет разбивать значения в массиве и будет считать его как один элемент

let records = {id: "5e8468e2db05ff589ca61b30",
title: "Example Application Number 1",
status: "Preparing Documents",
principalInvestigator: "Mr. Harry Styles",
coInvestigators: ["Niall Horan, Liam Payne, Zayn Malik, Louis Tomilson"]}


    const array = [Object.keys(records)].concat(records);

   let result = array.map(it => {

        let objectValues = Object.values(it);
        for (let i = 0; i < objectValues.length; i++) {
            if (Array.isArray(objectValues[i])) {
               objectValues[i]= objectValues[i]=(`[${objectValues[i].join(';')}]`).replace(/,/g, ';')
            }
        }

        return objectValues;
    }).join('\n');

    console.log(result);
0 голосов
/ 01 апреля 2020

Я бы лично предложил немного изменить ваше решение. Вам не нужно объединять ключи и значения, это делает .map() излишне сложным. Вот что я бы сделал:

var keys = Object.keys(records);
// we take the array of values, but we transform any array
// in a string of values separated by +
var values = Object.values(records).map(record => {
    if (Array.isArray(record))
        return record.join("+");
    return record;
});

// Now we can just put everything together
var result = keys.join(",") + "\n" + values.join(",");

console.log(result);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...