25

I want my application to go and find a excel file and convert it into a .xlsx file instead.

Here's what I'm currently doing;

var fileName = @"Z:\0328\orders\PurchaseOrder.csv";
FileInfo f = new FileInfo(fileName);
f.MoveTo(Path.ChangeExtension(fileName, ".xlsx"));
var Newfile = @"Z:\0328\orders\PurchaseOrder.xlsx";

Now this does work. It changes the file extension to my desired format. However, the file then become 'corrupt' or at least Excel refuses to open it and neither will my application when I try to venture further.

Does anyone have a solution/work-around?

5
  • 1
    you cannot do it by directly changing the file extension. Try to use any third party dll. Commented May 24, 2013 at 10:01
  • Could I open the file and save it as a new format? Possible? Commented May 24, 2013 at 10:03
  • Yes, open it and save to the new format will work. Should be possible to get an Excel VBA macro to do it, if that helps Commented May 24, 2013 at 10:04
  • You need to use something like the Open XML SDK from Microsoft to do that. However, unless you plan to add some additional features (embed formulas, fonts, colors, diagrams, etc.) you can simply stick with the CSV file, as Excel will open that happily. Commented May 24, 2013 at 10:06
  • You could use EPPlus or NPOI which allow you to write native XLSX files. Commented May 24, 2013 at 10:07

7 Answers 7

18

For those who want to use Interop instead of an external library, you can simply do this:

Application app = new Application();
Workbook wb = app.Workbooks.Open(@"C:\testcsv.csv", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
wb.SaveAs(@"C:\testcsv.xlsx", XlFileFormat.xlOpenXMLWorkbook, Type.Missing, Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
wb.Close();
app.Quit();

The second argument of Workbook.SaveAs determines the true format of the file. You should make the filename extension match that format so Excel doesn't complain about corruption. You can see a list of the types and what they mean on MSDN.

http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.xlfileformat.aspx

As always, please keep Microsoft's considerations in mind if this functionality is intended for a server environment. Interop may not be the way to go in that situation:

http://support.microsoft.com/kb/257757

Sign up to request clarification or add additional context in comments.

6 Comments

Just tested it - works perfectly well with Office 2013, thanks! Also wanted to add that in .net 4 you can skip all those nasty Type.Missing. You can simply call: Workbook wb = app.Workbooks.Open(csvPath); wb.SaveAs(xlsxPath, XlFileFormat.xlOpenXMLWorkbook, AccessMode: XlSaveAsAccessMode.xlExclusive);
@kDar - your code saves the file in Password protected mode.
How do I overwrite the file without showing a prompt to the user if a file already exist with that name?
@Si8 app.DisplayAlerts = false; before the save. REMEMBER to set it to true after! (app is the name of the Application, Application app = new Application();)
Thank you for the response @DDuffy... I was able to figure it out after looking through the API. Thanks for the help.
|
14

I would parse in the CSV file and use this to write out an Excel file : https://github.com/JanKallman/EPPlus

1 Comment

Second that - EPPlus is a great tool
7

This code should open the file you want and save it to the format without corrupting it.

  1. Renames the file
  2. Creates the Excel.Application instance
  3. Opens the file
  4. Does a save as to the desired format
  5. Closes it

    using Excel = Microsoft.Office.Interop.Excel;
    
    private void Convert_CSV_To_Excel()
    {
    
        // Rename .csv To .xls
        System.IO.File.Move(@"d:\Test.csv", @"d:\Test.csv.xls");
    
        var _app = new Excel.Application();
        var _workbooks = _app.Workbooks;
    
        _workbooks.OpenText("Test.csv.xls",
                                 DataType: Excel.XlTextParsingType.xlDelimited,
                                 TextQualifier: Excel.XlTextQualifier.xlTextQualifierNone,
                                 ConsecutiveDelimiter: true,
                                 Semicolon: true);
    
        // Convert To Excle 97 / 2003
        _workbooks[1].SaveAs("NewTest.xls", Excel.XlFileFormat.xlExcel5);
    
        _workbooks.Close();
    }
    

3 Comments

Can you explain your answer please? code-only answers are generally not acceptable because they don't necessarily help the asker to learn from their mistakes, etc.
+1 for xlExcel5 - because it does not give message that inner data is in other format when you open excel file.
It works also with _workbooks[1].SaveAs("testcsv.xlsx", Excel.XlFileFormat.xlWorkbookDefault); But rename the csv file to xls is necessary.
4

I would recommend using the following technique:

  1. http://kbcsv.codeplex.com/ this reads CSV files in very easily and is very robust.
  2. Create a datatable from the csv via the kbcsv extensions.
  3. Use the eppplus library and its LoadFromDataTable to create a valid xlsx file (https://github.com/JanKallman/EPPlus)
  4. done!

Advantages:

  • It is faster than excel interop
  • KBCSV is more robust than excels csv reading methods.
  • It is availabe in environments witohout office.

1 Comment

EPPLus can Load CSV directly via LoadFromText method :-) var range = sheet.Cells["A1"].LoadFromText(new FileInfo(CSV_FilePath), format, TableStyles.Medium27, true); Here is full example tinyurl.com/odyz25n
1

Try this class; takes in any CSV or TXT file with any delimiter including a tab and converts to Excel (.xls)

examples:

  • convertToExcel(@"path to file", "\t", ".csv");
  • convertToExcel(@"path to file", "\|", ".txt");

    public static void convertToExcel(string fileName, string splitter, string extension)
    {
        string newFileName = fileName.Replace("." + extension, ".xls");
    
        string[] lines = File.ReadAllLines(fileName, Encoding.UTF8);
    
        int columnCounter = 0;
    
        foreach (string s in lines)
        {
            string[] ss = s.Trim().Split(Convert.ToChar(splitter));
    
            if (ss.Length > columnCounter)
                columnCounter = ss.Length;
        }           
    
        HSSFWorkbook workbook = new HSSFWorkbook();
        var sheet = workbook.CreateSheet("Data");
        var rowIndex = 0;
        var rowExcel = sheet.CreateRow(rowIndex);
    
        foreach (string s in lines)
        {
            rowExcel = sheet.CreateRow(rowIndex);
    
            string[] ss = s.Trim().Split(Convert.ToChar(splitter));
    
            for (int i = 0; i < columnCounter; i++)
            {
                string data = !String.IsNullOrEmpty("s") && i < ss.Length ? ss[i] : "";
                rowExcel.CreateCell(i).SetCellType(CellType.String);
                rowExcel.CreateCell(i).SetCellValue(data);                    
            }
    
            rowIndex++;
        }
    
        for (var i = 0; i < sheet.GetRow(0).LastCellNum; i++)
            sheet.AutoSizeColumn(i);
    
        using (FileStream file = new FileStream(newFileName, FileMode.Create, FileAccess.Write))
        {
            workbook.Write(file);
            file.Close();
        }
    }
    

Comments

1
public static void ConvertFromCsvWithNpoi(string fileName, char splitter)
{
    var newFileName = Path.ChangeExtension(fileName, ".xlsx");
    string[] lines = File.ReadAllLines(fileName, Encoding.UTF8);

    IWorkbook workbook = new XSSFWorkbook();
    var sheet = workbook.CreateSheet(Path.GetFileName(newFileName));
    var rowIndex = 0;

    foreach (string line in lines)
    {
        var row = sheet.CreateRow(rowIndex);

        string[] lineStr = line.Trim().Split(splitter);

        for (int i = 0; i < lineStr.Length; i++)
        {
            string data = String.IsNullOrEmpty(line) ? string.Empty : lineStr[i].Trim();
            double sum = 0;
            if (double.TryParse(data, out sum))
            {
                row.CreateCell(i).SetCellValue(sum);
            }
            else
            {
                row.CreateCell(i).SetCellValue(data);
            }
        }

        rowIndex++;
    }

    for (var i = 0; i < sheet.GetRow(0).LastCellNum; i++)
        sheet.AutoSizeColumn(i);

    using (FileStream file = new FileStream(newFileName, FileMode.Create, FileAccess.Write))
    {
        workbook.Write(file);
        file.Close();
    }
}

2 Comments

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
Thank you very much, this helped me a lot. But one thing is wrong: Replace if (double.TryParse(data, out sum)) with if (double.TryParse(data, CultureInfo.InvariantCulture, out sum)) to prevent that a cell-value of 0.5 will wrongly be converted to 5 on a computer whose language has another decimal separator than . (for example on a german computer).
0

I would recommend Closed XML which is a wrapper around Open XML SDK. Check out their examples. It's pretty easy to create a .xlsx file.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.