简体   繁体   中英

How to convert xml to excel file programmatically

I have a xml document holding a small data for my project where I want to convert my xml to an excel file (microsoft office excel 2003 and over)

How can I do this programmatically?

It can be achieved by using Microsoft.Office.Interop.Excel as shown below:

First of all declare these necessary references.

using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.Office.Tools.Excel;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using System.Diagnostics;
using Microsoft.Win32;

Than create excel app as shown:

Excel.Application excel2; // Create Excel app
Excel.Workbook DataSource; // Create Workbook
Excel.Worksheet DataSheet; // Create Worksheet
excel2 = new Excel.Application(); // Start an Excel app
DataSource = (Excel.Workbook)excel2.Workbooks.Add(1); // Add a Workbook inside
string tempFolder = System.IO.Path.GetTempPath(); // Get folder 
string FileName = openFileDialog1.FileName.ToString(); // Get xml file name

After that use below code in a loop to ensure all items in xml file are copied

// Open that xml file with excel
DataSource = excel2.Workbooks.Open(FileName, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value);
// Get items from xml file
DataSheet = DataSource.Worksheets.get_Item(1);
// Create another Excel app as object
Object xl_app;
xl_app = GetObj(1, "Excel.Application");
Excel.Application xlApp = (Excel.Application)xl_app;
// Set previous Excel app (Xml) as ReportPage
Excel.Application ReportPage = (Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
// Copy items from ReportPage(Xml) to current Excel object
Excel.Workbook Copy_To_Excel = ReportPage.ActiveWorkbook;

Now we have an Excel object named as Copy_To_Excel that contains all items in Xml.. We can save and close the Excel object with the name we want..

Copy_To_Excel.Save("thePath\theFileName");
Copy_To_Excel.Close();

If you have control over the XML generated, just generate an XML Spreadsheet file (the XML file standard for Excel 2002 and 2003).

These open natively in Excel, without having to change the extension. (To open by default in Excel, the file extension XML should be set to open with "XML Editor", which is an Office app that routes the XML file to Excel, Word, PowerPoint, InfoPath, or your external XML editor as needed. This is the default mapping when Office is installed, but it may be out of whack for some users, particularly devs who edit XML files in a text editor.)

Or, use the NPOI library to generate a native (97/2000 BIFF/XLS) Excel file rather than XML.

您甚至可以将 XML 文件作为字符串读取并使用正则表达式读取标签之间的内容并创建 CSV 文件或使用 xpath 表达式读取 XML 文件数据并导出到 CSV 文件。

I know of no easy way to do code-based conversion from xml-based spreadsheet to xls/xlsx. But you might look into Microsoft Open Xml SDK which lets you work with xlsx. You might build xlsx spreadsheet and just feed it with your data. On the level of open-xml SDK it's like building xml file.

1.Fill the xml file into dataset,
2.convert dataset to excel by below method in asp.net

These are very simple methods.

  public static void Convert(System.Data.DataSet ds, System.Web.HttpResponse response)
    {
        //first let's clean up the response.object
        response.Clear();
        response.Charset = "";
        //set the response mime type for excel
        response.ContentType = "application/vnd.ms-excel";
        //create a string writer
        System.IO.StringWriter stringWrite = new System.IO.StringWriter();


        //create an htmltextwriter which uses the stringwriter
        System.Web.UI.HtmlTextWriter htmlWrite = new System.Web.UI.HtmlTextWriter(stringWrite);
        //instantiate a datagrid
        System.Web.UI.WebControls.DataGrid dg = new System.Web.UI.WebControls.DataGrid();
        //set the datagrid datasource to the dataset passed in
        dg.DataSource = ds.Tables[0];
        //bind the datagrid
        dg.DataBind();


        //tell the datagrid to render itself to our htmltextwriter
        dg.RenderControl(htmlWrite);
        //all that's left is to output the html
        response.Write(stringWrite.ToString());
        response.End();
    }

For array elements separate with ',' comma and reuse the same column name

1) XML Functions

public static class XMLFunctions
{       
    public static List<Tuple<string, string>> GetXMlTagsAndValues(string xml)
    {
        var xmlList = new List<Tuple<string, string>>();

        var doc = XDocument.Parse(xml);

        foreach (var element in doc.Descendants())
        {
            // we don't care about the parent tags
            if (element.Descendants().Count() > 0)
            {
                continue;
            }

            var path = element.AncestorsAndSelf().Select(e => e.Name.LocalName).Reverse();
            var xPath = string.Join("/", path); 

            xmlList.Add(Tuple.Create(xPath, element.Value));
        }

        return xmlList;
    }

    public static System.Data.DataTable CreateDataTableFromXmlFile(string xmlFilePath)
    {
        System.Data.DataTable Dt = new System.Data.DataTable();
        string input = File.ReadAllText(xmlFilePath);

        var xmlTagsAndValues = GetXMlTagsAndValues(input);
        var columnList = new List<string>();

        foreach(var xml in xmlTagsAndValues)
        {
            if(!columnList.Contains(xml.Item1))
            {
                columnList.Add(xml.Item1);
                Dt.Columns.Add(xml.Item1, typeof(string));
            }                    
        }

        DataRow dtrow = Dt.NewRow();
        var columnList2 = new Dictionary<string, string>(); 

        foreach (var xml in xmlTagsAndValues)
        {
            if (!columnList2.Keys.Contains(xml.Item1))
            {
                dtrow[xml.Item1] = xml.Item2;
                columnList2.Add(xml.Item1, xml.Item2);
            }
            else
            {   // Here we are using the same column but appending the next value
                dtrow[xml.Item1] = columnList2[xml.Item1] + "," + xml.Item2;

                columnList2[xml.Item1] = columnList2[xml.Item1] + "," + xml.Item2;
            }

        }

        Dt.Rows.Add(dtrow);

        return Dt;
    }
}

2) Full Excel class

using Microsoft.Office.Interop.Excel;
using _Excel = Microsoft.Office.Interop.Excel;

public class Excel 
{
    string path = "";
    Application excel = new _Excel.Application();
    Workbook wb;
    Worksheet ws;
    public Range xlRange;

    static bool saveChanges = false;
    static int excelRow = 0;
    static List<string> columnHeaders = new List<string>();    

    public Excel(string path, int Sheet = 1)
    {
        this.path = path;
        wb = excel.Workbooks.Open(path);
        ws = wb.Worksheets[Sheet];
        xlRange = ws.UsedRange;
        excelRow = 0;
        columnHeaders = new List<string>();
    }

    public void SaveFile(bool save = true)
    {
        saveChanges = save;
    }

    public void Close()
    {
        wb.Close(saveChanges);
        System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
        excel.Quit();
    }                      

    public void XMLToExcel(string xmlFilePath)
    {
        var dt = XMLFunctions.CreateDataTableFromXmlFile(xmlFilePath);
        AddDataTableToExcel(dt);
    }

    public void AddDataTableToExcel(System.Data.DataTable table)
    {       
        // Creating Header Column In Excel
        for (int i = 0; i < table.Columns.Count; i++)   
        {
            if (!columnHeaders.Contains(table.Columns[i].ColumnName))
            {
                ws.Cells[1, columnHeaders.Count() + 1] = table.Columns[i].ColumnName;
                columnHeaders.Add(table.Columns[i].ColumnName);
            }
        } 

        // Get the rows
        for (int k = 0; k < table.Columns.Count; k++)
        {
            var columnNumber = columnHeaders.FindIndex(x => x.Equals(table.Columns[k].ColumnName));

            ws.Cells[excelRow + 2, columnNumber + 1] = table.Rows[0].ItemArray[k].ToString();
        }

        excelRow++; 
        SaveFile(true);         
    }
}

3) Call it

var excel = new Excel(excelFilename);

foreach (var filePath in files)
{   
    excel.XMLToExcel(filePath); 
}

excel.Close();

For array elements having appended incremented column names (ex. column_2)

Create Data Table From XmlFile Redone

public static System.Data.DataTable CreateDataTableFromXmlFile(string xmlFilePath)
{
    System.Data.DataTable Dt = new System.Data.DataTable();

    string input = File.ReadAllText(xmlFilePath);

    var xmlTagsAndValues = GetXMlTagsAndValues(input);
    var columnList = new List<string>();

    foreach (var xml in xmlTagsAndValues)
    {
        if (!columnList.Contains(xml.Item1))
        {
            columnList.Add(xml.Item1);
            Dt.Columns.Add(xml.Item1, typeof(string));
        }                   
        else 
        {
            var columnName = xml.Item1;

            do
            {
                columnName = columnName.Increment();
            } while (columnList.Contains(columnName));

            columnList.Add(columnName);
            Dt.Columns.Add(columnName, typeof(string));

        }
    }

    DataRow dtrow = Dt.NewRow();
    var columnList2 = new Dictionary<string, string>();  

    foreach (var xml in xmlTagsAndValues)
    {
        if (!columnList2.Keys.Contains(xml.Item1))
        {
            dtrow[xml.Item1] = xml.Item2;
            columnList2.Add(xml.Item1, xml.Item2);
        }
        else
        {
            var columnName = xml.Item1;

            do
            {
                columnName = columnName.Increment();
            } while (columnList2.Keys.Contains(columnName));

            dtrow[columnName] = xml.Item2;
            columnList2[columnName] = xml.Item2;
        }           
    }

    Dt.Rows.Add(dtrow);

    return Dt;
}

String Extensions

public static class StringExtensions
{
    public static string Increment(this string str)
    {
        if (!str.Contains("_"))
        {
            str += "_2";
            return str;
        }

        var number = int.Parse(str.Substring(str.LastIndexOf('_') + 1));            

        var stringBefore = StringFunctions.GetUntilOrEmpty(str, "_");            

        return $"{stringBefore}_{++number}";
    }
}

Using GetUntilOrEmpty

How to open an XML file in Excel 2003 .

In short, you can simply open it by using FileOpen . Then, when you select an XML file, you are prompted to select one of the following methods to import the XML data:

  • As an XML list
  • As a read-only workbook
  • Use the XML Source task pane

Can't you simply open it in Excel? I thought Excel recognized the suffix XML?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM