Jak wyeksportować informacje o tablicy JavaScript do csv (po stronie klienta)?

511

Wiem, że jest wiele pytań tego rodzaju, ale muszę to zrobić za pomocą JavaScript. Używam Dojo 1.8i mam wszystkie informacje o atrybutach w tablicy, która wygląda następująco:

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

Masz pomysł, jak mogę to wyeksportować CSVpo stronie klienta?

Sam007
źródło

Odpowiedzi:

837

Możesz to zrobić w natywnym JavaScript. Będziesz musiał parsować swoje dane w odpowiednim formacie CSV (zakładając, że używasz tablic tablic dla swoich danych, jak opisano w pytaniu):

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";
});

lub w skrócie (za pomocą funkcji strzałek ):

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");

Następnie możesz użyć JavaScript window.openi encodeURIfunkcji, aby pobrać plik CSV w następujący sposób:

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

Edytować:

Jeśli chcesz nadać plikowi konkretną nazwę, musisz zrobić coś nieco inaczej, ponieważ nie jest to obsługiwane przy uzyskiwaniu dostępu do identyfikatora URI danych przy użyciu tej window.openmetody. Aby to osiągnąć, możesz utworzyć ukryty <a>węzeł DOM i ustawić jego downloadatrybut w następujący sposób:

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".
Domyślna
źródło
4
Z tego co wiem, nie da się tego zrobić za pomocą window.open. Możesz jednak utworzyć ukryty link, który ma downloadustawiony atrybut żądanej nazwy pliku. Następnie „kliknięcie” tego linku spowoduje pobranie pliku o żądanej nazwie, dodam go do mojej odpowiedzi.
Domyślnie
14
Musiałem dodać, document.body.appendChild(link);aby uzyskać pełne wsparcie w FF.
Hardbyte
9
Ta odpowiedź jest błędna: w przypadku się nie powiedzie data = [["Hello, world"]]. To wyświetli dwie kolumny, kiedy powinna wypisać jedną.
aredridel
18
Działa to dobrze dla około 7000 wierszy. Ale zaczyna dawać ten błąd: NETWORK_INVALID_REQUEST . Czy jakikolwiek organ również boryka się z tym problemem? Czy istnieje górna granica danych dotyczących encodeURIComponent()funkcji lub czegoś takiego? Używam Chrome jako przeglądarki.
Abhidemon,
13
@Abhidemon Odpowiedź jest taka, że ​​musisz użyć typu blob dla czegoś tak dużego, aby działało dobrze, np .: blob = new Blob ([csvContent], {type: "text / csv"}); href = window.URL.createObjectURL (obiekt blob); Więcej informacji: stackoverflow.com/a/19328891/1854079
mdubez
256

Na podstawie powyższych odpowiedzi stworzyłem tę funkcję, którą przetestowałem na IE 11, Chrome 36 i 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);
        }
    }
}

Na przykład: https://jsfiddle.net/jossef/m3rrLzk0/

Xavier John
źródło
6
Może spaść zwrotnie do window.openw elsez link.download !== undefined.
MrYellow
2
To niezły kawałek kodu. Czy jest jakaś szansa, że ​​zechcesz uzyskać licencję na coś bardziej liberalnego niż domyślna SO CC-BY-SA? Na przykład CC0, MIT, BSD, Apache, X11. . . meta.stackexchange.com/questions/12527/…
joseph_morris
1
Korzystałem z tej metody, aby zaimportować eksport do Excela w niektórych aplikacjach internetowych. Ale Chrome 43+ przeniósł teraz atrybuty DOM do łańcucha prototypów. Zgłoszony jest wyjątek link.style.visibility='hidden'. B / c atrybut DOM jest tylko do odczytu. Więcej szczegółów można znaleźć w aktualizacji.html5rocks.com/2015/04/... w sekcji „Zapisywanie właściwości tylko do odczytu w trybie ścisłym spowoduje błąd”
Blaise
1
Ta odpowiedź jest jak dotąd najlepsza. Obejmuje przypadki ze znakami specjalnymi i nawiasami.
Vladimir Kostov
2
Skorzystałem z sekcji pobierania tej odpowiedzi i zadziałało dobrze w Chrome, dzięki!
Liran H
77

To rozwiązanie powinno współpracować z Internet Explorer 10+, Edge, starymi i nowymi wersjami Chrome, FireFox, Safari, ++

Akceptowana odpowiedź nie będzie działać w IE i 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');

Uruchomienie fragmentu kodu spowoduje pobranie próbnych danych jako csv

Kredyty dla dandavis https://stackoverflow.com/a/16377813/1350598

Arne H. Bitubekk
źródło
1
(Przynajmniej kod HTML5) działa bez setTimeout.
StubbornShowaGuy
@StubbornShowaGuy cool, a następnie usunę setTimeout z przykładowego kodu :)
Arne H. Bitubekk
Działa w najnowszych przeglądarkach Chrome, IE i Firefox. Dzięki!
walla,
Jedyne dostępne rozwiązanie dla wielu przeglądarek. Uwaga: działa w przeglądarce Safari 10.10 i Safari na urządzeniach mobilnych. Jednak iframesekcję można zastąpić samą lokalizacją.
Dan
2
UWAGA: W funkcji jest literówka, tak naprawdę jest URL.createObjectURL(kończy się na URLnie Url).
Nathan Hinchey
35

Przybyłem tutaj, szukając nieco większej zgodności z RFC 4180 i nie udało mi się znaleźć implementacji, więc zrobiłem (być może nieefektywną) wersję na własne potrzeby. Myślałem, że podzielę się tym ze wszystkimi.

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');

Mam nadzieję, że pomoże to komuś w przyszłości. Łączy to zarówno kodowanie CSV, jak i możliwość pobrania pliku. W moim przykładzie na jsfiddle . Możesz pobrać plik (przy założeniu przeglądarki HTML 5) lub wyświetlić dane wyjściowe w konsoli.

AKTUALIZACJA:

Wygląda na to, że Chrome stracił teraz nazwę pliku. Nie jestem pewien, co się stało ani jak to naprawić, ale za każdym razem, gdy używam tego kodu (w tym jsfiddle), pobrany plik ma teraz nazwę download.csv.

Uxonith
źródło
Dobry połów Chris, nie testowałem tego z danymi liczbowymi :)
Uxonith,
Nie wiem, czy ostatnie sprawdzenie zerowe jest koniecznie oczekiwanym zachowaniem. Null różni się bardzo od pustego ciągu. Jeśli ktoś miałby to zaimplementować, poleciłbym niestandardową wartość zerową (np. „[[NULL]]”). Może być również pożądany wyjątek dla niezdefiniowanego, ale zalecałbym nie zastępowanie wartości null pustym ciągiem znaków.
Uxonith,
Testowałem i stwierdziłem, że masz rację. Wydaje się, że działa to w Chrome i Operze. Safari po prostu otwiera stronę z zawartością. Internet Explorer ... cóż, to IE. W mojej sytuacji mam zamiar wygenerować mój serwer CSV i tak mu służyć.
Uxonith,
33

Rozwiązanie @Default działa idealnie w Chrome (wielkie dzięki za to!), Ale miałem problem z IE.

Oto rozwiązanie (działa na 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")
Dzarek
źródło
23

W aktualizacji Chrome 35 zmieniono zachowanie atrybutu pobierania.

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

do pracy w chrome, użyj tego

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();
Monu
źródło
1
Możesz również to sprawdzić: github.com/mholt/PapaParse/issues/175#issuecomment-201308792
Gabriel
W tej chwili jest to poprawna odpowiedź, a nie ta oznaczona jako zaakceptowana!
meow
17

Działa we wszystkich językach

        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', '日本語'],
    ])
Serdar Didan
źródło
Imponujący! (+1). Witamy w StackOverflow, kolego!
Rann Lifshitz
czy możesz mi pomóc zrozumieć, co to jest blok kodu UTF-16 i do czego służy tutaj?
Mar1009,
Cześć Mar1009. Jest to wymagane w przypadku niektórych języków. Na przykład cyrylica.
Serdar Didan
13

Proszę bardzo :

<!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>  
Madhulika Mukherjee
źródło
1
Świetna odpowiedź. Głosuję za tym, ponieważ z jakiegoś powodu zaakceptowana odpowiedź umieszcza wszystko w jednej kolumnie. To wszystko dzieli na osobne kolumny, a obsługa formatu danych podobnego do JSON jest niezwykle przydatna.
Hoser
Działa to, gdy łącze jest najpierw dodawane do treści dokumentu, a następnie wywoływane jest kliknięcie. A następnie jest usuwany z dom.
Jay Dubal,
1
Dobra odpowiedź, jedyną wadą jest to, że nie działa poprawnie, gdy dane mają ogranicznik kolumny „,” tj. Adres: „10 nieskończonej linii pętli, pokój 56”, zauważ przecinek za linią. Proponuję użyć linku PapaParse do konwersji danych do CSV, a następnie użyć powyższej metody downloadCSV do rzeczywistego pobrania pliku
phil
To działa idealnie dla mnie. Mam tylko jeden problem, mam kilka liczb w tablicy, takich jak „000002342”, ale po wyeksportowaniu do csv zera wiodące są usuwane. Czy można temu zapobiec?
Aakarsh Dhawan
13

Ludzie próbują stworzyć własny ciąg csv, który nie działa na krawędziach, np. Znaki specjalne i takie, na pewno jest to rozwiązany problem, prawda?

papaparse - użyj do kodowania JSON na 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);
  }

}

Przykładowe użycie

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

https://github.com/mholt/PapaParse/issues/175 - Zobacz ten komentarz do dyskusji na temat obsługi przeglądarki.

Glen Thompson
źródło
10

Poniższego fragmentu kodu można użyć do wyeksportowania tablicy do pliku CSV przy użyciu Javascript.

Dotyczy to również części znaków specjalnych

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(); 

Oto link do działającego jsfiddle

Vignesh Subramanian
źródło
1
Najlepsza odpowiedź dla znaków specjalnych
Alejandro
# (hashtag) nie działa!
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
Mauri
źródło
6

Utwórz obiekt blob za pomocą pliku CSV .ie var blob = new Blob([data], type:"text/csv");

Jeśli przeglądarka obsługuje zapisywanie obiektów blob, tzn. if window.navigator.mSaveOrOpenBlob)===trueZapisz dane csv, używając: window.navigator.msSaveBlob(blob, 'filename.csv')

Jeśli przeglądarka nie obsługuje zapisywania i otwierania obiektów blob, zapisz dane csv jako:

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);

Pełny fragment kodu:

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(); 
}
Liyosi
źródło
5

Tutaj są dwa pytania:

  1. Jak przekonwertować tablicę na ciąg csv
  2. Jak zapisać ten ciąg do pliku

Wszystkie odpowiedzi na pierwsze pytanie (oprócz tego Milimetric) tutaj wydają się przesadą. A ten przez Milimetric nie obejmuje dodatkowych wymagań, takich jak otaczające ciągi znaków z cudzysłowami lub konwersja tablic obiektów.

Oto moje podejście do tego:

W przypadku zwykłego pliku csv wystarczy jedna mapa () i join ():

    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

Ta metoda pozwala również określić separator kolumn inny niż przecinek w złączeniu wewnętrznym. na przykład zakładka:d.join('\t')

Z drugiej strony, jeśli chcesz to zrobić poprawnie i zawrzeć ciągi w cudzysłowie „”, możesz użyć magii 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

jeśli masz tablicę obiektów takich jak:

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, '');
Konstantin
źródło
Jeśli się nie mylę, uważam, że .replacenależy podać nawiasy klamrowe vs. nawiasy kwadratowe.
aaronbartell
.replaceodbywa się na ciągu zwróconym przez values()który pobiera obiekt i zwraca tablicę wartości
Konstantin
values()Metoda nie została znaleziona, gdy próbowałem kodu.
aaronbartell
Dzięki! W Chrome działa bez values()wyraźnego połączenia Object. Poprawiłem przykład.
Konstantin
5

Wiele rozwiązań typu roll-your-own do konwertowania danych do CSV, ale prawie wszystkie będą miały różne zastrzeżenia dotyczące rodzaju danych, które poprawnie sformatują bez potknięcia Excela lub podobnych.

Dlaczego nie skorzystać z czegoś sprawdzonego: Papa Parse

Papa.unparse(data[, config])

Następnie po prostu połącz to z jednym z lokalnych rozwiązań pobierania np. ten autorstwa @ArneHB wygląda dobrze.

John Rix
źródło
4

Funkcja jednej strzałki w ES6:

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

Następnie :

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

Na wypadek, gdyby ktoś tego potrzebował , react-csvMa za to

Abdennour TOUMI
źródło
3
react-csvBiblioteka działa jak czar. Świetne rozwiązanie dla każdego, kto używa modułów.
Matt Parrilla
Nie uwzględnia to przypadku, w którym w pliku CSV znajdują się pola z przecinkami.
unpollito,
2

Oto jak pobieram pliki CSV po stronie klienta w mojej aplikacji Java GWT. Specjalne podziękowania dla Xaviera Johna za jego rozwiązanie. Sprawdzono działanie w FF 24.6.0, IE 11.0.20 i Chrome 45.0.2454.99 (64-bit). Mam nadzieję, że zaoszczędzi to komuś trochę czasu:

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);
            }
        }
    }-*/;
}
Justin Stein
źródło
1

Oto wersja przyjazna dla Angulara:

  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)}`);
    }
  };
Chrillewoodz
źródło
1

Powyższe odpowiedzi działają, ale pamiętaj, że jeśli otwierasz w formacie .xls, kolumny ~~ mogą ~~ być oddzielone '\t'zamiast ',', odpowiedź https://stackoverflow.com/a/14966131/6169225 działała dobrze dla mnie, o ile użyłem .join('\t')tablic zamiast .join(',').

Marquistador
źródło
działa dobrze dla plików .xls, BTW Mam drobny problem, gdy tekst jest zbyt długi i przekracza rozmiar siatki arkusz nie wygląda bardzo dobrze, jakaś wskazówka, aby to rozwiązać?
gabrielAnzaldo
1

Używam tej funkcji do konwersji string[][]do pliku csv. Cytuje komórkę, jeśli zawiera a ", a ,lub inną spację (z wyjątkiem pustych miejsc):

/**
 * 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

}

Uwaga : nie działa w przeglądarce Internet Explorer <11, chyba że mapjest wypełniony wielopełniaczowo.

Uwaga : Jeśli komórki zawierają liczby, możesz dodać cell=''+cellwcześniej, if (cell.replace...aby przekonwertować liczby na ciągi.

Lub możesz napisać w jednym wierszu za pomocą ES6:

t.map(r=>r.map(c=>c.replace(/ /g, '').match(/[\s,"]/)?'"'+c.replace(/"/g,'""')+'"':c).join(',')).join('\n')
Michael_Scharf
źródło
1

Polecam korzystanie z biblioteki takiej jak PapaParse: https://github.com/mholt/PapaParse

Akceptowana odpowiedź ma obecnie wiele problemów, w tym:

  • kończy się niepowodzeniem, jeśli dane zawierają przecinek
  • kończy się niepowodzeniem, jeśli dane zawierają podział wiersza
  • to (rodzaj) kończy się niepowodzeniem, jeśli dane zawierają znak cudzysłowu
Falk Tandetzky
źródło
1

Po prostu spróbuj tego, niektóre odpowiedzi tutaj nie obsługują danych Unicode i danych z przecinkiem, na przykład data.

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);
};
imal hasaranga perera
źródło
1

Pobierz plik 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();
Vik2696
źródło
1

Poniżej znajduje się natywne rozwiązanie 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>

dabeng
źródło
działało dla mnie idealnie. dzięki!
Srijani Ghosh
0

Jeśli ktoś potrzebuje tego do knockout js, działa w zasadzie z proponowanym rozwiązaniem:

HTML:

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

zobacz model:

// 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);
Milimetrowy
źródło
0

Dodałem do funkcji Xaviera Johnsa, aby w razie potrzeby uwzględnić również nagłówki pól, używa jQuery. Bit $ .each będzie wymagał zmiany dla natywnej pętli javascript

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);
        }
    }
}
Bim
źródło
0

To jest zmodyfikowana odpowiedź oparta na zaakceptowanej odpowiedzi, w której dane będą pochodzić z JSON.

            JSON Data Ouptut:
             0 :{emails: "SAMPLE Co., [email protected]"}, 1:{emails: "Another CO. , [email protected]"}


            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();
        });
Ronald G.
źródło
0

Jeśli szukasz naprawdę szybkiego rozwiązania, możesz również dać szansę tej małej bibliotece, która utworzy i pobierze dla Ciebie plik CSV: https://github.com/mbrn/filefy

Użycie jest bardzo proste:

import { CsvBuilder } from 'filefy';

var csvBuilder = new CsvBuilder("user_list.csv")
  .setColumns(["name", "surname"])
  .addRow(["Eve", "Holt"])
  .addRows([
    ["Charles", "Morris"],
    ["Tracey", "Ramos"]
  ])
  .exportFile();
Mladen Mitrovic
źródło