簡體   English   中英

將Excel Sheet導入ASP.NET Core Razor頁面后如何保存記錄

[英]How to save records after importing Excel Sheet into ASP.NET Core Razor pages

我試圖找到一種方法,可以將上載的excell工作表保存到數據庫Ms SQL服務器。

我有以下幾點:

模型

public class ImportDocs
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string LastName { get; set; }
    public string UserName { get; set; }
}

HTML和JavaScript用於查看記錄

<form method="post" enctype="multipart/form-data">
<div class="row">
    <div class="col-md-4">
        <input type="file" id="fUpload" name="files" class="form-control" />
    </div>
    <div class="col-md-8">
        <input type="button" id="btnUpload" value="Upload" />
    </div>
</div>
<br />
<div id="dvData"></div>
<br />
<div class="col-md-8">
    <input type="button" id="btnSave" value="Save To Database" />
</div>

JavaScript的

@Html.AntiForgeryToken()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js"> 
</script>
<script type="text/javascript">

$(document).ready(function () {
    $('#btnUpload').on('click', function () {
        var fileExtension = ['xls', 'xlsx'];
        var filename = $('#fUpload').val();
        if (filename.length == 0) {
            alert("Please select a file.");
            return false;
        }
        else {
            var extension = filename.replace(/^.*\./, '');
            if ($.inArray(extension, fileExtension) == -1) {
                alert("Please select only excel files.");
                return false;
            }
        }
        var fdata = new FormData();
        var fileUpload = $("#fUpload").get(0);
        var files = fileUpload.files;
        fdata.append(files[0].name, files[0]);
        $.ajax({
            type: "POST",
            url: "/ImportExcelFiles/Index?handler=Import",
            beforeSend: function (xhr) {
                xhr.setRequestHeader("XSRF-TOKEN",
                    $('input:hidden[name="__RequestVerificationToken"]').val());
            },
            data: fdata,
            contentType: false,
            processData: false,
            success: function (response) {
                if (response.length == 0)
                    alert('Some error occured while uploading');
                else {
                    $('#dvData').html(response);
                }
            },
            error: function (e) {
                $('#dvData').html(e.responseText);
            }
        });
    })
});

C#代碼

  private IHostingEnvironment _hostingEnvironment;
    public IndexModel(IHostingEnvironment hostingEnvironment)
    {
        _hostingEnvironment = hostingEnvironment;
    }
    public ActionResult OnPostImport()
    {
        IFormFile file = Request.Form.Files[0];
        string folderName = "Upload";
        string webRootPath = _hostingEnvironment.WebRootPath;
        string newPath = Path.Combine(webRootPath, folderName);
        StringBuilder sb = new StringBuilder();
        if (!Directory.Exists(newPath))
        {
            Directory.CreateDirectory(newPath);
        }
        if (file.Length > 0)
        {
            string sFileExtension = Path.GetExtension(file.FileName).ToLower();
            ISheet sheet;
            string fullPath = Path.Combine(newPath, file.FileName);
            using (var stream = new FileStream(fullPath, FileMode.Create))
            {
                file.CopyTo(stream);
                stream.Position = 0;
                if (sFileExtension == ".xls")
                {
                    HSSFWorkbook hssfwb = new HSSFWorkbook(stream); //This will read the Excel 97-2000 formats  
                    sheet = hssfwb.GetSheetAt(0); //get first sheet from workbook  
                }
                else
                {
                    XSSFWorkbook hssfwb = new XSSFWorkbook(stream); //This will read 2007 Excel format  
                    sheet = hssfwb.GetSheetAt(0); //get first sheet from workbook   
                }
                IRow headerRow = sheet.GetRow(0); //Get Header Row
                int cellCount = headerRow.LastCellNum;
                sb.Append("<table class='table'><tr>");
                for (int j = 0; j < cellCount; j++)
                {
                    NPOI.SS.UserModel.ICell cell = headerRow.GetCell(j);
                    if (cell == null || string.IsNullOrWhiteSpace(cell.ToString())) continue;
                    sb.Append("<th>" + cell.ToString() + "</th>");
                }
                sb.Append("</tr>");
                sb.AppendLine("<tr>");
                for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++) //Read Excel File
                {
                    IRow row = sheet.GetRow(i);
                    if (row == null) continue;
                    if (row.Cells.All(d => d.CellType == CellType.Blank)) continue;
                    for (int j = row.FirstCellNum; j < cellCount; j++)
                    {
                        if (row.GetCell(j) != null)
                            sb.Append("<td>" + row.GetCell(j).ToString() + "</td>");
                    }
                    sb.AppendLine("</tr>");
                }
                sb.Append("</table>");
            }
        }
        return this.Content(sb.ToString());
    }
}

我該如何存檔

你快到了。 您需要使用Reflection檢查excel並構造一個ImportDocs列表,以便我們可以將IList<ImportDocs>保存到數據庫中。

服務器端的過程可以分為四個部分:

  1. 使用當前請求創建ISheet的實例
  2. 使用工作表創建一個ImportDocs列表(我們將其命名為“ records”)
  3. 將記錄列表保存到數據庫
  4. 構建html <table>...</table>以便客戶端顯示

這是頁面模型的結構:

    private IHostingEnvironment _hostingEnvironment; // injected by DI
    private AppDbContext _dbContext;                 // injected by DI


    public IActionResult OnPostSave(){
        var sheet = this.ParseSheetFromRequest(false);
        var records = this.ParseDocsFromSheet(sheet);
        var sb = this.BuildTableHtml(records);
        // typically, we'll use Database to generate the Id
        //     as we cannot trust user 
        foreach (var record in records) {
            record.Id = default(int);  
        }
        this._dbContext.ImportDocs.AddRange(records);
        this._dbContext.SaveChanges();
        return this.Content(sb==null?"":sb.ToString());
    }

    public IActionResult OnPostImport(){
        var sheet = this.ParseSheetFromRequest(true);
        var records = this.ParseDocsFromSheet(sheet);
        var sb = this.BuildTableHtml(records);
        return this.Content(sb==null?"":sb.ToString());
    }

    private ISheet ParseSheetFromRequest(bool saveFile) { 
        // ...
    }

    private List<ImportDocs> ParseDocsFromSheet(ISheet sheet){
        // ...
    }
    private StringBuilder BuildTableHtml<T>(IList<T> records){   
        // ...
    }

這里的ParseSheetFromRequest()是用於根據當前請求創建新的ISheet的幫助器方法,我只需復制您的代碼即可:

    private ISheet ParseSheetFromRequest(bool saveFile) {
        ISheet sheet= null;
        IFormFile file = Request.Form.Files[0];
        if (file.Length ==0 ) {
            return sheet;
        }

        string sFileExtension = Path.GetExtension(file.FileName).ToLower();
        var stream = file.OpenReadStream();
        if (sFileExtension == ".xls") {
            HSSFWorkbook hssfwb = new HSSFWorkbook(stream); //This will read the Excel 97-2000 formats  
            sheet = hssfwb.GetSheetAt(0); //get first sheet from workbook  
        }
        else {
            XSSFWorkbook hssfwb = new XSSFWorkbook(stream); //This will read 2007 Excel format  
            sheet = hssfwb.GetSheetAt(0); //get first sheet from workbook   
        }

        var records = this.ParseDocsFromSheet(sheet);

        // if need to save the file
        if (saveFile) {
            stream = file.OpenReadStream();
            string folderName = "Upload";
            string webRootPath = _hostingEnvironment.WebRootPath;
            string newPath = Path.Combine(webRootPath, folderName);
            if (!Directory.Exists(newPath)) {
                Directory.CreateDirectory(newPath);
            }
            string fullPath = Path.Combine(newPath, file.FileName);
            using (var fileStream= new FileStream(fullPath, FileMode.Create)) {
                file.CopyTo(fileStream);
            }
        }

        return sheet;
    }

ParseDocsFromSheet()是另一個用於從工作表中解析ImportDocs幫助方法。 它使用Reflection來檢查字段名稱,然后在運行時構造一個新的強類型實例:

    private List<ImportDocs> ParseDocsFromSheet(ISheet sheet){

        IRow headerRow = sheet.GetRow(0); //Get Header Row
        int cellCount = headerRow.LastCellNum;
        // ["Id","LastName","","UserName","","Name"]
        var headerNames= new List<string>();
        for (int j = 0; j < cellCount; j++)
        {
            NPOI.SS.UserModel.ICell cell = headerRow.GetCell(j);
            if (cell == null || string.IsNullOrWhiteSpace(cell.ToString())) {
                headerNames.Add("");  // add empty string if cell is empty
            }else{
                headerNames.Add( cell.ToString());
            }
        }

        var records= new List<ImportDocs>();

        for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++) //Read Excel File
        {
            IRow row = sheet.GetRow(i);
            if (row == null) continue;
            if (row.Cells.All(d => d.CellType == CellType.Blank)) continue;
            var record = new ImportDocs();
            var type = typeof(ImportDocs);
            for (int j = 0 ; j < cellCount; j++)
            {
                if (row.GetCell(j) != null){
                    var field = row.GetCell(j).ToString();
                    var fieldName = headerNames[j];
                    if(String.IsNullOrWhiteSpace(fieldName)){
                        throw new Exception($"There's a value in Cell({i},{j}) but has no header !");
                    }
                    var pi = type.GetProperty(fieldName);
                    // for Id column : a int type
                    if(pi.PropertyType.IsAssignableFrom(typeof(Int32))){
                        pi.SetValue(record,Convert.ToInt32(field));
                    }
                    // for other colun : string
                    else{
                        pi.SetValue(record,field);
                    }
                }
            }
            records.Add(record);
        }
        return records;
    }

最后,要構建<table> ,我們可以創建一個可重用的方法:

    private StringBuilder BuildTableHtml<T>(IList<T> records)
        where T: class
    {
        var type = typeof(T);
        var pis = type.GetProperties();

        var sb = new StringBuilder();
        sb.Append("<table class='table'><tr>");
        foreach(var pi in pis){
            sb.Append("<th>" + pi.Name + "</th>");
        }
        sb.Append("</tr>");
        foreach (var record in records) //Read Excel File
        {
            sb.AppendLine("<tr>");
            foreach(var pi in pis){
                sb.Append("<td>" + pi.GetValue(record) + "</td>");
            }
            sb.AppendLine("<tr>");
        }
        sb.Append("</table>");
        return sb;
    }

測試用例:

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM