วิธีการส่งออกข้อมูลอาร์เรย์ JavaScript ไปยัง csv (ทางฝั่งไคลเอ็นต์)


511

ฉันรู้ว่ามีคำถามมากมายในลักษณะนี้ แต่ฉันต้องทำสิ่งนี้โดยใช้ JavaScript ฉันใช้Dojo 1.8และมีข้อมูลคุณลักษณะทั้งหมดในอาร์เรย์ซึ่งมีลักษณะดังนี้:

[["name1", "city_name1", ...]["name2", "city_name2", ...]]

ความคิดใด ๆ ที่ฉันสามารถส่งออกไปยังCSVด้านลูกค้า?

คำตอบ:


837

คุณสามารถทำได้ใน JavaScript ดั้งเดิม คุณจะต้องวิเคราะห์ข้อมูลของคุณให้อยู่ในรูปแบบ CSV ที่ถูกต้องเช่นนั้น (สมมติว่าคุณใช้อาร์เรย์ของข้อมูลตามที่อธิบายไว้ในคำถาม):

const rows = [
    ["name1", "city1", "some other info"],
    ["name2", "city2", "more info"]
];

let csvContent = "data:text/csv;charset=utf-8,";

rows.forEach(function(rowArray) {
    let row = rowArray.join(",");
    csvContent += row + "\r\n";
});

หรือวิธีที่สั้นกว่า (โดยใช้ฟังก์ชั่นลูกศร ):

const rows = [
    ["name1", "city1", "some other info"],
    ["name2", "city2", "more info"]
];

let csvContent = "data:text/csv;charset=utf-8," 
    + rows.map(e => e.join(",")).join("\n");

จากนั้นคุณสามารถใช้ JavaScript window.openและencodeURIฟังก์ชั่นเพื่อดาวน์โหลดไฟล์ CSV ดังนี้:

var encodedUri = encodeURI(csvContent);
window.open(encodedUri);

แก้ไข:

หากคุณต้องการตั้งชื่อเฉพาะให้กับไฟล์คุณต้องทำสิ่งต่าง ๆ เล็กน้อยเนื่องจากไม่รองรับการเข้าถึงข้อมูล URI โดยใช้window.openวิธีการ เพื่อให้บรรลุเป้าหมายนี้คุณสามารถสร้าง<a>โหนด DOM ที่ซ่อนอยู่และตั้งค่าdownloadแอตทริบิวต์ดังต่อไปนี้:

var encodedUri = encodeURI(csvContent);
var link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", "my_data.csv");
document.body.appendChild(link); // Required for FF

link.click(); // This will download the data file named "my_data.csv".

4
window.openจากสิ่งที่ฉันรู้ว่ามีไม่ได้เป็นวิธีที่จะทำโดยใช้ อย่างไรก็ตามคุณสามารถสร้างลิงค์ที่ซ่อนอยู่ซึ่งมีการdownloadตั้งค่าคุณสมบัติเป็นชื่อไฟล์ที่คุณต้องการ จากนั้น "คลิก" ลิงก์นี้จะดาวน์โหลดไฟล์ในชื่อที่คุณต้องการฉันจะเพิ่มลงในคำตอบของฉัน
เริ่มต้น

14
ฉันต้องเพิ่มdocument.body.appendChild(link);เพื่อรับการสนับสนุนอย่างเต็มที่ใน FF
Hardbyte

9
คำตอบนี้ผิด: จะล้มเหลวในกรณีdata = [["Hello, world"]]นี้ ที่จะส่งออกสองคอลัมน์เมื่อมันควรจะออกหนึ่ง
aredridel

18
วิธีนี้ใช้ได้ผลเช่น ~ 7000 แถว แต่จะเริ่มต้นให้ข้อผิดพลาดนี้: NETWORK_INVALID_REQUEST มีร่างอื่นที่กำลังประสบปัญหานี้ด้วยหรือไม่? มีขีด จำกัด ของข้อมูลบนencodeURIComponent()ฟังก์ชั่นหรือบางอย่าง? ฉันใช้ Chrome เป็นเบราว์เซอร์
Abhidemon

13
@Abhidemon คำตอบคือคุณต้องใช้ชนิด blob สำหรับสิ่งที่มีขนาดใหญ่แล้วมันจะทำงานได้ดีเช่น: blob = new Blob ([csvContent], {type: "text / csv"}); href = window.URL.createObjectURL (หยด); รายละเอียดเพิ่มเติม: stackoverflow.com/a/19328891/1854079
mdubez

256

จากคำตอบข้างต้นฉันได้สร้างฟังก์ชั่นนี้ซึ่งฉันได้ทดสอบกับ IE 11, Chrome 36 และ Firefox 29

function exportToCsv(filename, rows) {
    var processRow = function (row) {
        var finalVal = '';
        for (var j = 0; j < row.length; j++) {
            var innerValue = row[j] === null ? '' : row[j].toString();
            if (row[j] instanceof Date) {
                innerValue = row[j].toLocaleString();
            };
            var result = innerValue.replace(/"/g, '""');
            if (result.search(/("|,|\n)/g) >= 0)
                result = '"' + result + '"';
            if (j > 0)
                finalVal += ',';
            finalVal += result;
        }
        return finalVal + '\n';
    };

    var csvFile = '';
    for (var i = 0; i < rows.length; i++) {
        csvFile += processRow(rows[i]);
    }

    var blob = new Blob([csvFile], { type: 'text/csv;charset=utf-8;' });
    if (navigator.msSaveBlob) { // IE 10+
        navigator.msSaveBlob(blob, filename);
    } else {
        var link = document.createElement("a");
        if (link.download !== undefined) { // feature detection
            // Browsers that support HTML5 download attribute
            var url = URL.createObjectURL(blob);
            link.setAttribute("href", url);
            link.setAttribute("download", filename);
            link.style.visibility = 'hidden';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
    }
}

ตัวอย่างเช่น: https://jsfiddle.net/jossef/m3rrLzk0/


6
อาจตกกลับไปwindow.openในของelse link.download !== undefined
MrYellow

2
นี่เป็นโค้ดที่ดี มีโอกาสใดที่คุณยินดีที่จะอนุญาตให้ใช้สิทธินี้ภายใต้บางสิ่งที่มากกว่าการเริ่มต้นของ CC-BY-SA ตัวอย่างเช่น CC0, MIT, BSD, Apache, X11 . . meta.stackexchange.com/questions/12527/…
joseph_morris

1
ฉันใช้วิธีนี้เพื่อนำการส่งออก Excel ไปใช้ในเว็บแอพพลิเคชัน แต่ตอนนี้ Chrome 43+ ได้ย้ายแอตทริบิวต์ DOM ไปยังเชนต้นแบบ มีข้อยกเว้นเกิดlink.style.visibility='hidden'ขึ้นที่ B / c แอตทริบิวต์ DOM อ่านได้อย่างเดียว รายละเอียดเพิ่มเติมสามารถหาได้ในupdates.html5rocks.com/2015/04/ ภายใต้หัวข้อ "คุณสมบัติการเขียนเพื่ออ่านอย่างเดียวในโหมดเข้มงวดจะทำให้เกิดข้อผิดพลาด"
Blaise

1
การตอบสนองนี้เป็นสิ่งที่ดีที่สุดจนถึงปัจจุบัน มันรวมถึงกรณีที่มีตัวอักษรพิเศษและวงเล็บ
Vladimir Kostov

2
ฉันใช้ส่วนดาวน์โหลดของคำตอบนี้และใช้งานได้ดีกับ Chrome ขอบคุณ!
Liran H

77

โซลูชันนี้ควรทำงานกับInternet Explorer 10+, Edge, Chromeรุ่นเก่าและใหม่, FireFox, Safari, ++

คำตอบที่ยอมรับจะไม่ทำงานกับ IE และ Safari

// Example data given in question text
var data = [
  ['name1', 'city1', 'some other info'],
  ['name2', 'city2', 'more info']
];

// Building the CSV from the Data two-dimensional array
// Each column is separated by ";" and new line "\n" for next row
var csvContent = '';
data.forEach(function(infoArray, index) {
  dataString = infoArray.join(';');
  csvContent += index < data.length ? dataString + '\n' : dataString;
});

// The download function takes a CSV string, the filename and mimeType as parameters
// Scroll/look down at the bottom of this snippet to see how download is called
var download = function(content, fileName, mimeType) {
  var a = document.createElement('a');
  mimeType = mimeType || 'application/octet-stream';

  if (navigator.msSaveBlob) { // IE10
    navigator.msSaveBlob(new Blob([content], {
      type: mimeType
    }), fileName);
  } else if (URL && 'download' in a) { //html5 A[download]
    a.href = URL.createObjectURL(new Blob([content], {
      type: mimeType
    }));
    a.setAttribute('download', fileName);
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
  } else {
    location.href = 'data:application/octet-stream,' + encodeURIComponent(content); // only this mime type is supported
  }
}

download(csvContent, 'dowload.csv', 'text/csv;encoding:utf-8');

การเรียกใช้ข้อมูลโค้ดจะเป็นการดาวน์โหลดข้อมูลจำลองเป็น csv

ให้เครดิตกับ dandavis https://stackoverflow.com/a/16377813/1350598


1
(อย่างน้อยที่สุดรหัส HTML5) setTimeoutที่ทำงานได้โดยไม่ต้อง
StubbornShowaGuy

@StubbornShowaGuy เย็นแล้วฉันจะลบ setTimeout จากโค้ดตัวอย่าง :)
อาร์เอช Bitubekk

ใช้งานได้กับ Chrome, IE และ Firefox ล่าสุด ขอบคุณ!
walla

โซลูชันเบราว์เซอร์ข้ามที่แท้จริงอย่างเดียวเท่านั้นที่นี่ สังเกตว่าใช้งานได้กับ Safari 10.10 และ Safari มือถือ อย่างไรก็ตามiframeส่วนนี้สามารถแทนที่ได้โดยเพียงแค่ location.href = ...
ด่าน

2
หมายเหตุ: มีการพิมพ์ผิดในฟังก์ชั่นมันเป็นจริงURL.createObjectURL(ลงท้ายด้วยURLไม่Url)
Nathan Hinchey

35

ฉันมาที่นี่เพื่อหาการปฏิบัติตาม RFC 4180 อีกเล็กน้อยและฉันไม่พบการใช้งานดังนั้นฉันจึงทำ (ที่ไม่มีประสิทธิภาพ) สำหรับความต้องการของฉันเอง ฉันคิดว่าฉันจะแบ่งปันกับทุกคน

var content = [['1st title', '2nd title', '3rd title', 'another title'], ['a a a', 'bb\nb', 'cc,c', 'dd"d'], ['www', 'xxx', 'yyy', 'zzz']];

var finalVal = '';

for (var i = 0; i < content.length; i++) {
    var value = content[i];

    for (var j = 0; j < value.length; j++) {
        var innerValue =  value[j]===null?'':value[j].toString();
        var result = innerValue.replace(/"/g, '""');
        if (result.search(/("|,|\n)/g) >= 0)
            result = '"' + result + '"';
        if (j > 0)
            finalVal += ',';
        finalVal += result;
    }

    finalVal += '\n';
}

console.log(finalVal);

var download = document.getElementById('download');
download.setAttribute('href', 'data:text/csv;charset=utf-8,' + encodeURIComponent(finalVal));
download.setAttribute('download', 'test.csv');

หวังว่านี่จะช่วยใครบางคนในอนาคต รวมการเข้ารหัสของ CSV พร้อมกับความสามารถในการดาวน์โหลดไฟล์ ในตัวอย่างของฉันในjsfiddle คุณสามารถดาวน์โหลดไฟล์ (สมมติว่าเบราว์เซอร์ HTML 5) หรือดูผลลัพธ์ในคอนโซล

UPDATE:

ตอนนี้ Chrome ดูเหมือนจะสูญเสียความสามารถในการตั้งชื่อไฟล์ ผมไม่แน่ใจว่าสิ่งที่เกิดขึ้นหรือวิธีการแก้ไขมัน แต่เมื่อใดก็ตามที่ฉันใช้รหัสนี้ (รวม jsfiddle) download.csvจากไฟล์ที่ดาวน์โหลดมาเป็นชื่อตอนนี้


จับดีคริสผมไม่ได้ทดสอบกับข้อมูลที่เป็นตัวเลข :)
Uxonith

ฉันไม่รู้ว่าการตรวจสอบโมฆะครั้งสุดท้ายนั้นเป็นพฤติกรรมที่คาดหวังหรือไม่ Null แตกต่างจากสตริงว่างมาก หากมีการใช้งานนี้ฉันจะแนะนำค่า null ที่กำหนดเอง (เช่น: '[[NULL]]') อาจต้องการยกเว้นสำหรับ undefined เช่นกัน แต่ฉันขอแนะนำไม่ให้แทนที่ null ด้วยสตริงว่าง
Uxonith

ฉันกำลังทดสอบและพบว่าคุณถูกต้อง ดูเหมือนว่าจะใช้งานได้ใน Chrome และ Opera Safari เพียงเปิดหน้าเว็บที่มีเนื้อหา Internet Explorer ... ก็คือ IE สำหรับสถานการณ์ของฉันฉันจะสร้างฝั่งเซิร์ฟเวอร์ CSV ของฉันและให้บริการอย่างนั้นเศร้า
Uxonith

33

โซลูชันจาก @Default ทำงานได้อย่างสมบูรณ์บน Chrome (ขอบคุณมากสำหรับสิ่งนั้น!) แต่ฉันมีปัญหากับ IE

นี่เป็นวิธีแก้ปัญหา (ใช้งานได้บน IE10):

var csvContent=data; //here we load our csv data 
var blob = new Blob([csvContent],{
    type: "text/csv;charset=utf-8;"
});

navigator.msSaveBlob(blob, "filename.csv")

23

ในการอัปเดต Chrome 35 การทำงานของแอตทริบิวต์การดาวน์โหลดก็เปลี่ยนไป

https://code.google.com/p/chromium/issues/detail?id=373182

ในการทำงานในโครเมี่ยมให้ใช้สิ่งนี้

var pom = document.createElement('a');
var csvContent=csv; //here we load our csv data 
var blob = new Blob([csvContent],{type: 'text/csv;charset=utf-8;'});
var url = URL.createObjectURL(blob);
pom.href = url;
pom.setAttribute('download', 'foo.csv');
pom.click();

1
คุณสามารถตรวจสอบสิ่งนี้: github.com/mholt/PapaParse/issues/175#issuecomment-201308792
Gabriel

นี่เป็นคำตอบที่ถูกต้องในขณะนี้ไม่ใช่คำตอบที่ถูกยอมรับ!
meow

17

ทำงานได้กับทุกภาษา

        function convertToCsv(fName, rows) {
        var csv = '';
        for (var i = 0; i < rows.length; i++) {
            var row = rows[i];
            for (var j = 0; j < row.length; j++) {
                var val = row[j] === null ? '' : row[j].toString();
                val = val.replace(/\t/gi, " ");
                if (j > 0)
                    csv += '\t';
                csv += val;
            }
            csv += '\n';
        }

        // for UTF-16
        var cCode, bArr = [];
        bArr.push(255, 254);
        for (var i = 0; i < csv.length; ++i) {
            cCode = csv.charCodeAt(i);
            bArr.push(cCode & 0xff);
            bArr.push(cCode / 256 >>> 0);
        }

        var blob = new Blob([new Uint8Array(bArr)], { type: 'text/csv;charset=UTF-16LE;' });
        if (navigator.msSaveBlob) {
            navigator.msSaveBlob(blob, fName);
        } else {
            var link = document.createElement("a");
            if (link.download !== undefined) {
                var url = window.URL.createObjectURL(blob);
                link.setAttribute("href", url);
                link.setAttribute("download", fName);
                link.style.visibility = 'hidden';
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
                window.URL.revokeObjectURL(url);
            }
        }
    }



    convertToCsv('download.csv', [
        ['Order', 'Language'],
        ['1', 'English'],
        ['2', 'Español'],
        ['3', 'Français'],
        ['4', 'Português'],
        ['5', 'čeština'],
        ['6', 'Slovenščina'],
        ['7', 'Tiếng Việt'],
        ['8', 'Türkçe'],
        ['9', 'Norsk bokmål'],
        ['10', 'Ελληνικά'],
        ['11', 'беларускі'],
        ['12', 'русский'],
        ['13', 'Українська'],
        ['14', 'հայերեն'],
        ['15', 'עִברִית'],
        ['16', 'اردو'],
        ['17', 'नेपाली'],
        ['18', 'हिंदी'],
        ['19', 'ไทย'],
        ['20', 'ქართული'],
        ['21', '中国'],
        ['22', '한국어'],
        ['23', '日本語'],
    ])

ที่น่าประทับใจ! (+1) ยินดีต้อนรับสู่ StackOverflow เพื่อน!
Rann Lifshitz

คุณช่วยฉันเข้าใจว่าโค้ดบล็อค UTF-16 นั้นคืออะไรและใช้ที่นี่ได้อย่างไร
Mar1009

สวัสดี Mar1009 สิ่งนี้จำเป็นสำหรับบางภาษา ตัวอย่างเช่นตัวอักษรซิริลลิก
Serdar Didan

13

ไปที่นั่น:

<!doctype html>  
<html>  
<head></head>  
<body>
<a href='#' onclick='downloadCSV({ filename: "stock-data.csv" });'>Download CSV</a>

<script type="text/javascript">  
    var stockData = [
        {
            Symbol: "AAPL",
            Company: "Apple Inc.",
            Price: "132.54"
        },
        {
            Symbol: "INTC",
            Company: "Intel Corporation",
            Price: "33.45"
        },
        {
            Symbol: "GOOG",
            Company: "Google Inc",
            Price: "554.52"
        },
    ];

    function convertArrayOfObjectsToCSV(args) {
        var result, ctr, keys, columnDelimiter, lineDelimiter, data;

        data = args.data || null;
        if (data == null || !data.length) {
            return null;
        }

        columnDelimiter = args.columnDelimiter || ',';
        lineDelimiter = args.lineDelimiter || '\n';

        keys = Object.keys(data[0]);

        result = '';
        result += keys.join(columnDelimiter);
        result += lineDelimiter;

        data.forEach(function(item) {
            ctr = 0;
            keys.forEach(function(key) {
                if (ctr > 0) result += columnDelimiter;

                result += item[key];
                ctr++;
            });
            result += lineDelimiter;
        });

        return result;
    }

    window.downloadCSV = function(args) {
        var data, filename, link;

        var csv = convertArrayOfObjectsToCSV({
            data: stockData
        });
        if (csv == null) return;

        filename = args.filename || 'export.csv';

        if (!csv.match(/^data:text\/csv/i)) {
            csv = 'data:text/csv;charset=utf-8,' + csv;
        }
        data = encodeURI(csv);

        link = document.createElement('a');
        link.setAttribute('href', data);
        link.setAttribute('download', filename);
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
       }
</script>  
</body>  
</html>  

1
คำตอบที่ยอดเยี่ยม ฉัน upvoting หนึ่งนี้เป็นคำตอบที่ยอมรับด้วยเหตุผลบางอย่างทำให้ทุกอย่างในคอลัมน์เดียว สิ่งนี้จะแบ่งมันออกเป็นคอลัมน์แยกต่างหากและการสนับสนุนรูปแบบข้อมูล JSON นั้นมีประโยชน์อย่างเหลือเชื่อ
Hoser

สิ่งนี้จะทำงานเมื่อลิงค์ถูกเพิ่มไปยังเนื้อหาของเอกสารเป็นครั้งแรกจากนั้นคลิกจะถูกเรียก แล้วมันจะถูกลบออกจากโดม
Jay Dubal

1
คำตอบที่ดีข้อเสียเปรียบเพียงอย่างเดียวคือมันไม่ทำงานอย่างถูกต้องเมื่อข้อมูลมีตัวคั่นคอลัมน์ "," เช่นที่อยู่: '10 ช่องทางวนรอบไม่สิ้นสุดห้อง 56 'สังเกตเห็นเครื่องหมายจุลภาคหลังช่อง ฉันขอแนะนำให้คุณใช้ลิงก์ PapaParse เพื่อแปลงข้อมูลเป็น CSV จากนั้นใช้วิธีการดาวน์โหลดข้างต้น CSV สำหรับการดาวน์โหลดไฟล์จริง
phil

มันใช้งานได้สมบูรณ์แบบสำหรับฉัน เพียงมีปัญหาเดียวฉันมีตัวเลขบางอย่างในอาร์เรย์เช่น '000002342' แต่เมื่อส่งออกไปยัง csv เลขศูนย์นำหน้าจะถูกลบออก มีวิธีใดในการป้องกันสิ่งนี้หรือไม่?
Aakarsh Dhawan

13

คนพยายามสร้างสตริง csv ของตนเองซึ่งล้มเหลวในกรณีที่ขอบเช่นตัวอักษรพิเศษและเช่นนั้นแน่นอนว่านี่เป็นปัญหาที่แก้ไขได้ใช่ไหม?

papaparse - ใช้สำหรับการเข้ารหัส JSON เป็น CSV Papa.unparse().

import Papa from "papaparse";

const downloadCSV = (args) => {  

  let filename = args.filename || 'export.csv';
  let columns = args.columns || null;

  let csv = Papa.unparse({ data: args.data, fields: columns})
  if (csv == null) return;

  var blob = new Blob([csv]);
  if (window.navigator.msSaveOrOpenBlob)  // IE hack; see http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx
      window.navigator.msSaveBlob(blob, args.filename);
  else
  {
      var a = window.document.createElement("a");
      a.href = window.URL.createObjectURL(blob, {type: "text/plain"});
      a.download = filename;
      document.body.appendChild(a);
      a.click();  // IE: "Access is denied"; see: https://connect.microsoft.com/IE/feedback/details/797361/ie-10-treats-blob-url-as-cross-origin-and-denies-access
      document.body.removeChild(a);
  }

}

ตัวอย่างการใช้งาน

downloadCSV({ 
  filename: 'filename.csv',
  data: [{'a': '1', 'b': 2'}],
  columns: ['a','b']
});

https://github.com/mholt/PapaParse/issues/175 - ดูความคิดเห็นนี้สำหรับการสนทนาการสนับสนุนเบราว์เซอร์


10

คุณสามารถใช้โค้ดด้านล่างเพื่อส่งออกอาร์เรย์ไปยังไฟล์ CSV โดยใช้ Javascript

นี้จัดการส่วนอักขระพิเศษเช่นกัน

var arrayContent = [["Séjour 1, é,í,ú,ü,ű"],["Séjour 2, é,í,ú,ü,ű"]];
var csvContent = arrayContent.join("\n");
var link = window.document.createElement("a");
link.setAttribute("href", "data:text/csv;charset=utf-8,%EF%BB%BF" + encodeURI(csvContent));
link.setAttribute("download", "upload_data.csv");
link.click(); 

นี่คือลิงค์ไปยัง jsfiddle ที่ใช้งานได้


1
คำตอบที่ดีที่สุดสำหรับตัวละครพิเศษ
Alejandro

# (hashtag) ไม่ทำงาน!
Nakres

7
//It work in Chrome and IE ... I reviewed and readed a lot of answer. then i used it and tested in both ... 

var link = document.createElement("a");

if (link.download !== undefined) { // feature detection
    // Browsers that support HTML5 download attribute
    var blob = new Blob([CSV], { type: 'text/csv;charset=utf-8;' });
    var url = URL.createObjectURL(blob);            
    link.setAttribute("href", url);
    link.setAttribute("download", fileName);
    link.style = "visibility:hidden";
}

if (navigator.msSaveBlob) { // IE 10+
   link.addEventListener("click", function (event) {
     var blob = new Blob([CSV], {
       "type": "text/csv;charset=utf-8;"
     });
   navigator.msSaveBlob(blob, fileName);
  }, false);
}

document.body.appendChild(link);
link.click();
document.body.removeChild(link);

//Regards

6

สร้าง blob ด้วย csv data .ie var blob = new Blob([data], type:"text/csv");

หากเบราว์เซอร์รองรับการบันทึก blobs เช่น if window.navigator.mSaveOrOpenBlob)===trueให้บันทึกข้อมูล csv โดยใช้: window.navigator.msSaveBlob(blob, 'filename.csv')

หากเบราว์เซอร์ไม่รองรับการบันทึกและการเปิด blobs ให้บันทึกข้อมูล csv เป็น:

var downloadLink = document.createElement('<a></a>');
downloadLink.attr('href', window.URL.createObjectURL(blob));
downloadLink.attr('download', filename);
downloadLink.attr('target', '_blank');
document.body.append(downloadLink);

ข้อมูลโค้ดแบบเต็ม:

var filename = 'data_'+(new Date()).getTime()+'.csv';
var charset = "utf-8";
var blob = new Blob([data], {
     type: "text/csv;charset="+ charset + ";"
});
if (window.navigator.msSaveOrOpenBlob) {
     window.navigator.msSaveBlob(blob, filename);
} else {
    var downloadLink = document.element('<a></a>');
    downloadLink.attr('href', window.URL.createObjectURL(blob));
    downloadLink.attr('download', filename);
    downloadLink.attr('target', '_blank');  
    document.body.append(downloadLink); 
    downloadLink[0].click(); 
}

5

มีสองคำถามที่นี่:

  1. วิธีการแปลงอาร์เรย์เป็นสตริง csv
  2. วิธีบันทึกสตริงนั้นลงในไฟล์

คำตอบทั้งหมดสำหรับคำถามแรก (ยกเว้นคำตอบโดย Milimetric) ที่นี่ดูเหมือนว่าเกินความจริง และหนึ่งโดย Milimetric ไม่ครอบคลุมข้อกำหนด altrenative เช่นสายโดยรอบด้วยคำพูดหรือแปลงอาร์เรย์ของวัตถุ

นี่คือเวลาของฉันในเรื่องนี้:

สำหรับ csv อย่างง่ายหนึ่งแผนที่ () และการเข้าร่วม () ก็เพียงพอแล้ว:

    var test_array = [["name1", 2, 3], ["name2", 4, 5], ["name3", 6, 7], ["name4", 8, 9], ["name5", 10, 11]];
    var csv = test_array.map(function(d){
        return d.join();
    }).join('\n');

    /* Results in 
    name1,2,3
    name2,4,5
    name3,6,7
    name4,8,9
    name5,10,11

วิธีนี้ยังช่วยให้คุณสามารถระบุตัวแยกคอลัมน์นอกเหนือจากเครื่องหมายจุลภาคในการเข้าร่วมภายใน เช่นแท็บ:d.join('\t')

ในทางกลับกันหากคุณต้องการทำอย่างถูกต้องและใส่สตริงในเครื่องหมายคำพูด "" คุณสามารถใช้เวทมนตร์ JSON:

var csv = test_array.map(function(d){
       return JSON.stringify(d);
    })
    .join('\n') 
    .replace(/(^\[)|(\]$)/mg, ''); // remove opening [ and closing ]
                                   // brackets from each line 

/* would produce
"name1",2,3
"name2",4,5
"name3",6,7
"name4",8,9
"name5",10,11

หากคุณมีอาร์เรย์ของวัตถุเช่น:

var data = [
  {"title": "Book title 1", "author": "Name1 Surname1"},
  {"title": "Book title 2", "author": "Name2 Surname2"},
  {"title": "Book title 3", "author": "Name3 Surname3"},
  {"title": "Book title 4", "author": "Name4 Surname4"}
];

// use
var csv = data.map(function(d){
        return JSON.stringify(Object.values(d));
    })
    .join('\n') 
    .replace(/(^\[)|(\]$)/mg, '');

หากฉันไม่ผิดฉันเชื่อว่า.replaceควรระบุหยิกกับวงเล็บเหลี่ยม
aaronbartell

.replaceจะทำในสตริงที่ส่งกลับโดยvalues()ที่ใช้วัตถุและส่งกลับอาร์เรย์ของค่า
Konstantin

values()วิธีไม่พบเมื่อฉันพยายามรหัสของคุณ
aaronbartell

ขอบคุณ! ใน Chrome มันทำงานได้โดยไม่ต้องโทรอย่างชัดเจนบนvalues() Objectฉันแก้ไขตัวอย่าง
Konstantin

5

โซลูชั่นม้วนของคุณเองมากมายที่นี่สำหรับการแปลงข้อมูลเป็น CSV แต่เกือบทั้งหมดจะมีคำเตือนต่าง ๆ ในแง่ของประเภทข้อมูลที่พวกเขาจะจัดรูปแบบอย่างถูกต้องโดยไม่ต้องสะดุด Excel หรือสิ่งที่ชอบ

ทำไมไม่ใช้สิ่งที่พิสูจน์แล้ว: Papa Parse

Papa.unparse(data[, config])

จากนั้นเพียงรวมเข้ากับหนึ่งในโซลูชันการดาวน์โหลดในพื้นที่ที่นี่เช่น หนึ่งโดย @ArneHB ดูดี


4

ฟังก์ชันลูกศรหนึ่งด้วย ES6:

const dataToCsvURI = (data) => encodeURI(
`data:text/csv;charset=utf-8,${data.map((row, index) =>  row.join(',')).join(`\n`)}`
);

จากนั้น:

window.open(
  dataToCsvURI(
   [["name1", "city_name1"/*, ...*/], ["name2", "city_name2"/*, ...*/]]
  )
);

ในกรณีที่ทุกคนต้องการสิ่งนี้เพื่อ , react-csvมีที่


3
react-csvห้องสมุดทำงานเช่นเสน่ห์ ทางออกที่ดีสำหรับทุกคนที่ใช้โมดูล
Matt Parrilla

สิ่งนี้ไม่สามารถสังเกตเห็นกรณีที่มีฟิลด์อยู่ภายในไฟล์ CSV ที่มีเครื่องหมายจุลภาคอยู่ภายใน
unpollito

2

นี่คือวิธีที่ฉันดาวน์โหลดไฟล์ CSV ที่ฝั่งไคลเอ็นต์ในแอปพลิเคชัน Java GWT ของฉัน ขอขอบคุณ Xavier John เป็นพิเศษสำหรับวิธีการแก้ปัญหาของเขา ผ่านการตรวจสอบแล้วว่าทำงานใน FF 24.6.0, IE 11.0.20 และ Chrome 45.0.2454.99 (64-bit) ฉันหวังว่าสิ่งนี้จะช่วยให้ใครบางคนประหยัดเวลา:

public class ExportFile 
{

    private static final String CRLF = "\r\n";

    public static void exportAsCsv(String filename, List<List<String>> data) 
    {
        StringBuilder sb = new StringBuilder();
        for(List<String> row : data) 
        {
            for(int i=0; i<row.size(); i++)
            {
                if(i>0) sb.append(",");
                sb.append(row.get(i));
            }
            sb.append(CRLF);
        }

        generateCsv(filename, sb.toString());
    }

    private static native void generateCsv(String filename, String text)
    /*-{
        var blob = new Blob([text], { type: 'text/csv;charset=utf-8;' });

        if (navigator.msSaveBlob) // IE 10+
        { 
            navigator.msSaveBlob(blob, filename);
        } 
        else 
        {
            var link = document.createElement("a");
            if (link.download !== undefined) // feature detection
            { 
                // Browsers that support HTML5 download attribute
                var url = URL.createObjectURL(blob);
                link.setAttribute("href", url);
                link.setAttribute("download", filename);
                link.style.visibility = 'hidden';
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
            }
        }
    }-*/;
}

2

ต่อไปนี้เป็นโซลูชัน js ดั้งเดิม

function export2csv() {
  let data = "";
  const tableData = [];
  const rows = [
    ['111', '222', '333'],
    ['aaa', 'bbb', 'ccc'],
    ['AAA', 'BBB', 'CCC']
  ];
  for (const row of rows) {
    const rowData = [];
    for (const column of row) {
      rowData.push(column);
    }
    tableData.push(rowData.join(","));
  }
  data += tableData.join("\n");
  const a = document.createElement("a");
  a.href = URL.createObjectURL(new Blob([data], { type: "text/csv" }));
  a.setAttribute("download", "data.csv");
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
}
<button onclick="export2csv()">Export array to csv file</button>


ทำงานอย่างสมบูรณ์แบบสำหรับฉัน ขอบคุณ!
Srijani Ghosh

1

นี่เป็นเวอร์ชั่นที่เป็นมิตรเชิงมุม:

  constructor(private location: Location, private renderer: Renderer2) {}

  download(content, fileName, mimeType) {

    const a = this.renderer.createElement('a');

    mimeType = mimeType || 'application/octet-stream';

    if (navigator.msSaveBlob) {

      navigator.msSaveBlob(new Blob([content], {
        type: mimeType
      }), fileName);
    }
    else if (URL && 'download' in a) {

      const id = GetUniqueID();

      this.renderer.setAttribute(a, 'id', id);
      this.renderer.setAttribute(a, 'href', URL.createObjectURL(new Blob([content], {
        type: mimeType
      })));

      this.renderer.setAttribute(a, 'download', fileName);

      this.renderer.appendChild(document.body, a);

      const anchor = this.renderer.selectRootElement(`#${id}`);

      anchor.click();

      this.renderer.removeChild(document.body, a);
    }
    else {
      this.location.go(`data:application/octet-stream,${encodeURIComponent(content)}`);
    }
  };

1

คำตอบข้างต้นใช้งานได้ แต่โปรดจำไว้ว่าหากคุณเปิดในรูปแบบ. xls คอลัมน์ ~~ อาจ ~~ คั่นด้วย'\t'แทนที่จะ','เป็นคำตอบhttps://stackoverflow.com/a/14966131/6169225ทำงานได้ดี สำหรับฉันดังนั้นตราบใดที่ผมใช้ในอาร์เรย์แทน.join('\t').join(',')


ทำงานได้ดีสำหรับไฟล์. xls, BTW ฉันมีปัญหาเล็กน้อยเมื่อข้อความยาวเกินไปและเกินขนาดของกริดแผ่นงานดูไม่ดีนัก
gabrielAnzaldo

1

ฉันใช้ฟังก์ชันนี้เพื่อแปลงstring[][]ไฟล์เป็น csv มันเป็นเครื่องหมายคำพูดของเซลล์ถ้ามันมี", ,หรือช่องว่างอื่น ๆ (ยกเว้นช่องว่าง):

/**
 * Takes an array of arrays and returns a `,` sparated csv file.
 * @param {string[][]} table
 * @returns {string}
 */
function toCSV(table) {
    return table
        .map(function(row) {
            return row
                .map(function(cell) {
                    // We remove blanks and check if the column contains
                    // other whitespace,`,` or `"`.
                    // In that case, we need to quote the column.
                    if (cell.replace(/ /g, '').match(/[\s,"]/)) {
                        return '"' + cell.replace(/"/g, '""') + '"';
                    }
                    return cell;
                })
                .join(',');
        })
        .join('\n'); // or '\r\n' for windows

}

หมายเหตุ : ใช้งานไม่ได้กับ Internet Explorer <11 ยกเว้นว่าmapเป็น polyfilled

หมายเหตุ : หากเซลล์มีตัวเลขคุณสามารถเพิ่มcell=''+cellก่อนif (cell.replace...เพื่อแปลงตัวเลขเป็นสตริง

หรือคุณสามารถเขียนมันในหนึ่งบรรทัดโดยใช้ ES6:

t.map(r=>r.map(c=>c.replace(/ /g, '').match(/[\s,"]/)?'"'+c.replace(/"/g,'""')+'"':c).join(',')).join('\n')

1

ฉันอยากจะแนะนำให้ใช้ห้องสมุดเช่น PapaParse: https://github.com/mholt/PapaParse

คำตอบที่ยอมรับในปัจจุบันมีหลายประเด็น ได้แก่ :

  • มันล้มเหลวหากข้อมูลมีเครื่องหมายจุลภาค
  • มันล้มเหลวหากข้อมูลมีการหยุดสาย
  • มัน (ชนิด) ล้มเหลวหากข้อมูลมีเครื่องหมายคำพูด

1

เพียงลองสิ่งนี้คำตอบบางส่วนที่นี่ไม่ได้จัดการข้อมูล unicode และข้อมูลที่มีเครื่องหมายจุลภาคเช่นวันที่

function downloadUnicodeCSV(filename, datasource) {
    var content = '', newLine = '\r\n';
    for (var _i = 0, datasource_1 = datasource; _i < datasource_1.length; _i++) {
        var line = datasource_1[_i];
        var i = 0;
        for (var _a = 0, line_1 = line; _a < line_1.length; _a++) {
            var item = line_1[_a];
            var it = item.replace(/"/g, '""');
            if (it.search(/("|,|\n)/g) >= 0) {
                it = '"' + it + '"';
            }
            content += (i > 0 ? ',' : '') + it;
            ++i;
        }
        content += newLine;
    }
    var link = document.createElement('a');
    link.setAttribute('href', 'data:text/csv;charset=utf-8,%EF%BB%BF' + encodeURIComponent(content));
    link.setAttribute('download', filename);
    link.style.visibility = 'hidden';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
};

1

ดาวน์โหลดไฟล์ CSV

  let csvContent = "data:text/csv;charset=utf-8,";
  rows.forEach(function (rowArray) {
    for (var i = 0, len = rowArray.length; i < len; i++) {
      if (typeof (rowArray[i]) == 'string')
        rowArray[i] = rowArray[i].replace(/<(?:.|\n)*?>/gm, '');
      rowArray[i] = rowArray[i].replace(/,/g, '');
    }

    let row = rowArray.join(",");
    csvContent += row + "\r\n"; // add carriage return
  });
  var encodedUri = encodeURI(csvContent);
  var link = document.createElement("a");
  link.setAttribute("href", encodedUri);
  link.setAttribute("download", "fileName.csv");
  document.body.appendChild(link);
  link.click();

0

ในกรณีที่ทุกคนต้องการสิ่งนี้สำหรับสิ่งที่น่าพิศวง js มันใช้งานได้ดีกับโซลูชันที่เสนอโดยทั่วไป:

HTML:

<a data-bind="attr: {download: filename, href: csvContent}">Download</a>

ดูรูปแบบ:

// for the download link
this.filename = ko.computed(function () {
    return ko.unwrap(this.id) + '.csv';
}, this);
this.csvContent = ko.computed(function () {
    if (!this.csvLink) {
        var data = ko.unwrap(this.data),
            ret = 'data:text/csv;charset=utf-8,';

        ret += data.map(function (row) {
            return row.join(',');
        }).join('\n');

        return encodeURI(ret);
    }
}, this);

0

ฉันได้เพิ่มฟังก์ชัน Xavier Johns เพื่อรวมส่วนหัวของฟิลด์หากจำเป็นให้ใช้ jQuery บิต $ .each จะต้องเปลี่ยนเป็น javascript loop แบบดั้งเดิม

function exportToCsv(filename, rows, headers = false) {
    var processRow = function (row) {
        row = $.map(row, function(value, index) {
            return [value];
        });
        var finalVal = '';
        for (var j = 0; j < row.length; j++) {
            if(i == 0 && j == 0 && headers == true){
                var ii = 0;
                $.each(rows[i], function( index, value ) {
                    //console.log(index);
                    var fieldName = index === null ? '' : index.toString();
                    //console.log(fieldName);
                    var fieldResult = fieldName.replace(/"/g, '""');
                    //console.log(fieldResult);
                    if (fieldResult.search(/("|,|\n)/g) >= 0){
                        fieldResult = '"' + fieldResult + '"';
                    }
                    //console.log(fieldResult);
                    if (ii > 0){
                        finalVal += ',';
                        finalVal += fieldResult;
                    }else{
                        finalVal += fieldResult;
                    }
                    ii++;
                    //console.log(finalVal);
                });
                finalVal += '\n';
                //console.log('end: '+finalVal);
            }
            var innerValue = row[j] === null ? '' : row[j].toString();
            if (row[j] instanceof Date) {
                innerValue = row[j].toLocaleString();
            };
            var result = innerValue.replace(/"/g, '""');
            if (result.search(/("|,|\n)/g) >= 0){
                result = '"' + result + '"';
            }
            if (j > 0){
                finalVal += ',';
                finalVal += result;
            }else{
                finalVal += result;
            }
        }
        return finalVal + '\n';
    };
    var csvFile = '';
    for (var i = 0; i < rows.length; i++) {
        csvFile += processRow(rows[i]);
    }
    var blob = new Blob([csvFile], { type: 'text/csv;charset=utf-8;' });
    if (navigator.msSaveBlob) { // IE 10+
        navigator.msSaveBlob(blob, filename);
    }else{
        var link = document.createElement("a");
        if (link.download !== undefined) { // feature detection
            // Browsers that support HTML5 download attribute
            var url = URL.createObjectURL(blob);
            link.setAttribute("href", url);
            link.setAttribute("download", filename);
            link.style.visibility = 'hidden';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
    }
}

0

นี่เป็นคำตอบที่แก้ไขตามคำตอบที่ยอมรับซึ่งข้อมูลจะมาจาก JSON

            JSON Data Ouptut:
             0 :{emails: "SAMPLE Co., peter@samplecompany.com"}, 1:{emails: "Another CO. , ronald@another.com"}


            JS:
            $.getJSON('yourlink_goes_here', { if_you_have_parameters}, function(data) {
            var csvContent = "data:text/csv;charset=utf-8,";
            var dataString = '';
             $.each(data, function(k, v) {
                dataString += v.emails + "\n";
             });

            csvContent += dataString;

            var encodedUri = encodeURI(csvContent);
            var link = document.createElement("a");
            link.setAttribute("href", encodedUri);
            link.setAttribute("download", "your_filename.csv");
            document.body.appendChild(link); // Required for FF

            link.click();
        });

0

หากคุณกำลังมองหาทางออกที่รวดเร็วจริงๆคุณสามารถให้โอกาสกับห้องสมุดขนาดเล็กซึ่งจะสร้างและดาวน์โหลดไฟล์ CSV สำหรับคุณ: https://github.com/mbrn/filefy

การใช้งานง่ายมาก:

import { CsvBuilder } from 'filefy';

var csvBuilder = new CsvBuilder("user_list.csv")
  .setColumns(["name", "surname"])
  .addRow(["Eve", "Holt"])
  .addRows([
    ["Charles", "Morris"],
    ["Tracey", "Ramos"]
  ])
  .exportFile();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.