2016-11-09 30 views
0

我目前正試圖從我的應用程序以Excel或CSV導出一些數據。什麼是完成這個最好的方法?我應該從後端導出還是導出一次在Angular 2中使用庫的數據客戶端?我的Web API 2控制器當前生成一個列表,然後將其作爲JSON發送到前端。將數據導出爲ex​​cel的正確方法?

這一切工作,我只是在出口清單掙扎。

下面是我在做什麼

[HttpGet] 
[Route("/api/preview/{item}")] 
public IActionResult Preview(string item) 
{  
    if (item!= null) 
    { 
     var preview = _context.dbPreview.FromSql("Exec sampleStoredProcedure {0}, 1", item).ToList(); 

     return Ok(preview); 
    } 
} 

樣本也就是說我如何生成我的數據發送到角2

我可以提供任何角2碼,如果有必要但這只是一項正常的服務。不知道是否有一些庫與Angular 2可以很好地進行導出。我已經看到了一些JavaScript,但alaSQL的東西,但它似乎不會像Angular 2一樣工作。

任何想法?

+0

你有數據客戶端,那麼我認爲最好的是使用JavaScript來創建一個CSV文件。例如[PrimeNG](http://www.primefaces.org/primeng/#/datatable/export)可以導出csv文件。 (服務器端也是可能的。) – AWolf

+0

我看着PrimeNG數據表導出,但我不確定是否有辦法在不顯示數據表本身的情況下觸發導出。該表是數據量非常大,並在頁面上顯示它似乎不合理。這就是爲什麼我想將其導出而不顯示在頁面上的原因。有任何想法嗎? @AWolf – dev53

+0

Powershell有一個名爲Export-csv的cmdlet,它非常易於使用,前提是您的數據組織良好。不知道是否要將PowerShell添加到您的工具箱中。 –

回答

1

我查看了PrimeNG DataTable的源代碼,我想你可以使用exportCSV代碼導出csv的數據。

「訣竅」是生成一個以data:text/csv;charset=utf-8開頭的字符串,並由用戶下載。

像下面的代碼應該爲你工作(也許你需要修改它,所以它適合你的數據)。

大多數代碼是從PrimeNG複製的,除了下載方法。該方法從SO answer複製而來。

import { Component } from '@angular/core'; 

@Component({ 
    selector: 'app-root', 
    templateUrl: './app.component.html', 
    styleUrls: ['./app.component.css'] 
}) 
export class AppComponent { 
    title = 'app works!'; 

    csvSeparator = ';'; 

    value = [ 
     { name: 'A3', year: 2013, brand: 'Audi' }, 
     { name: 'Z3', year: 2015, brand: 'BMW' } 
    ]; 

    columns = [ 
     { field: 'name', header: 'Name' }, 
     { field: 'year', header: 'Production data' }, 
     { field: 'brand', header: 'Brand' }, 
    ]; 

    constructor() { 

     console.log(this.value); 
     this.exportCSV('cars.csv'); // just for show casing --> later triggered by a click on a button 
    } 

    download(text, filename) { 
     let element = document.createElement('a'); 
     element.setAttribute('href', 'data:text/csv;charset=utf-8,' + encodeURIComponent(text)); 
     element.setAttribute('download', filename); 

     element.style.display = 'none'; 
     document.body.appendChild(element); 

     element.click(); 

     document.body.removeChild(element); 
    } 

    exportCSV(filename) { 
     let data = this.value, csv = ''; 
     // csv = "data:text/csv;charset=utf-8,"; 

     //headers 
     for (let i = 0; i < this.columns.length; i++) { 
      if (this.columns[i].field) { 
       csv += this.columns[i].field; 

       if (i < (this.columns.length - 1)) { 
        csv += this.csvSeparator; 
       } 
      } 
     } 

     //body   
     this.value.forEach((record, j) => { 
      csv += '\n'; 
      for (let i = 0; i < this.columns.length; i++) { 
       if (this.columns[i].field) { 
        console.log(record[this.columns[i].field]); 
        // resolveFieldData seems to check if field is nested e.g. data.something --> probably not needed 
        csv += record[this.columns[i].field]; //this.resolveFieldData(record, this.columns[i].field); 

        if (i < (this.columns.length - 1)) { 
         csv += this.csvSeparator; 
        } 
       } 
      } 
     }); 
     // console.log(csv); 
     // window.open(encodeURI(csv)); // doesn't display a filename! 
     this.download(csv, filename); 
    } 

    // resolveFieldData(data: any, field: string): any { 
    //  if(data && field) { 
    //   if(field.indexOf('.') == -1) { 
    //    return data[field]; 
    //   } 
    //   else { 
    //    let fields: string[] = field.split('.'); 
    //    let value = data; 
    //    for(var i = 0, len = fields.length; i < len; ++i) { 
    //     value = value[fields[i]]; 
    //    } 
    //    return value; 
    //   } 
    //  } 
    //  else { 
    //   return null; 
    //  } 
    // } 


} 
+0

非常感謝。這對我有用。唯一的問題是,目前它在Internet Explorer中不起作用。去看看我能找到一些解決方法。 – dev53

0

AWolfs的回答讓我在正確的軌道上,但我做了一些調整,以得到它與Internet Explorer工作。

此函數將我的數組轉換爲我的csv文件的字符串。 (我不得不創建一個新的對象,這是我的列標題)。然後我只是將由我的服務生成的數據傳遞給該函數,併爲我執行解析。對於更復雜的數據,我相信你需要做一些額外的邏輯,但我有基本的文本,所以這一切都爲我解決。

exportCSV(filename, CsvData) { 
    let data = CsvData, csv = ''; 

    console.log(data); 
    //headers 
    for (let i = 0; i < this.columns.length; i++) { 
     if (this.columns[i].field) { 
      csv += this.columns[i].field; 

      if (i < (this.columns.length - 1)) { 
       csv += this.csvSeparator; 
      } 
     } 
    } 

    //body   
    CsvData.forEach((record, j) => { 
     csv += '\n'; 
     for (let i = 0; i < this.columns.length; i++) { 
      if (this.columns[i].field) { 
       console.log(record[this.columns[i].field]); 
       csv += record[this.columns[i].field]; 
       if (i < (this.columns.length - 1)) { 
        csv += this.csvSeparator; 
       } 
      } 
     } 
    }); 
    this.DownloadFile(csv, filename); 
} 

這是幾乎一樣AWolfs回答,但我不得不做出一些修改DownloadFile函數來獲取它與其他瀏覽器的工作。該函數只接受構成.CSV文件和文件名的大字符串。

DownloadFile(text, filename) { 
    console.log(text); 
    var blob = new Blob([text], { type: 'text/csv;charset=utf-8;' }); 
    if (navigator.msSaveBlob) { // IE 10+ 
     navigator.msSaveBlob(blob, filename); 
    } 
    else //create a link and click it 
    { 
     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); 
     } 
    } 
} 

此代碼需要清理,但我想更新我的問題,併爲任何正在與同一事情苦苦掙扎的人解答。這至少應該讓你開始。這適用於Chrome和IE。

謝謝。

+0

看起來不錯,你是對的IE瀏覽器真的是我的代碼問題,因爲它不支持'下載'屬性(Safari也不支持它)。經過一些谷歌搜索後,我發現[文件保護程序](https://www.npmjs.com/package/file-saver)做得非常好。所以你不需要下載方法,你可以使用'filesaver.saveAs(blob,filename);'。導入模塊有點棘手,但是這個[git問題](https://github.com/angular/angular-cli/issues/999)會起作用。 – AWolf