2016-11-09 80 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