简体   繁体   中英

OpenXML Writing Values to Empty Cells in Excel

I have figured out how to write the contents of a string array to Excel in the format I want but now I'm having trouble making sure it doesn't write over cells that are already populated in an Excel file.

Currently I am trying to read the contents of the Excel file first then insert based off of where there are no values. This is what I currently have.

private static void WriteToExcel(string[] contents, char[] desiredColumns)
{
    string filePath = @"D:\Folder\test.xlsx";
    try
    {
        using (SpreadsheetDocument StatsCollection = SpreadsheetDocument.Open(filePath, true))
        {
            WorkbookPart bookPart = StatsCollection.WorkbookPart;
            string sheetName = "Sheet1";
            SharedStringTablePart sstpart = bookPart.GetPartsOfType<SharedStringTablePart>().First();
            SharedStringTable sst = sstpart.SharedStringTable;
            Sheet mySheet = bookPart.Workbook.Descendants<Sheet>().Where(s => s.Name == sheetName).FirstOrDefault();
            WorksheetPart sheetPart = (WorksheetPart)(bookPart.GetPartById(mySheet.Id));
            Worksheet sheet = sheetPart.Worksheet;
            var rows = sheet.Descendants<Row>();
            foreach (Row row in rows)
            {
                foreach (Cell currentCell in row.Elements<Cell>())
                {
                    int totalRows = contents.Length / 15;
                    int contentsIndex = 0;
                    for (uint indexRow = 1; indexRow <= totalRows; indexRow++)
                    {
                        for (int indexCol = 1; indexCol < 16; indexCol++)
                        {
                            SharedStringTablePart shareStringPart;
                            if (StatsCollection.WorkbookPart.GetPartsOfType<SharedStringTablePart>().Count() > 0)
                            {
                                shareStringPart = StatsCollection.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First();
                            }
                            else
                            {
                                shareStringPart = StatsCollection.WorkbookPart.AddNewPart<SharedStringTablePart>();
                            }
                            int index = InsertSharedStringItem(contents[contentsIndex], shareStringPart);
                            if (currentCell.CellValue.InnerText == "")
                            {
                                Cell newCell = InsertCellInWorksheet(desiredColumns[indexCol - 1].ToString(), indexRow, sheetPart);
                                if (IsNumeric(contents[contentsIndex]))
                                {
                                    newCell.DataType = new EnumValue<CellValues>(CellValues.Number);
                                    newCell.CellValue = new CellValue(contents[contentsIndex]);
                                }
                                else
                                {
                                    newCell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
                                    newCell.CellValue = new CellValue(index.ToString());
                                }
                            }
                            else
                            {
                                break;
                            }
                            sheetPart.Worksheet.Save();
                            contentsIndex++;
                        }
                    }
                }
            }
        }
        Console.WriteLine("Copy Complete.");
    }
    catch (Exception ex)
    {
        Console.WriteLine("Cannot find output Excel file.\n" + ex.Message);
    }
}

My thought process here was that if I could use the code to read in the information on my Excel sheet I found here I could then insert where that is null . Once I've determined if something is null I then break from my most inner loop (which handles my columns) to increment my outer loop (which handles rows). However that doesn't seem to be working. I've verified that I am in fact reading the information from the sheet I just can't seem to write based off of that.

Why can I read the contents of my file but not write based on the cells that are there?

Update:

For anyone who comes across this question I ended up switching to Microsoft.Office.Interop to append my data onto the end of an excel file. I'm hesitant to put that as an answer because it doesn't answer how to do it in OpenXML, which was my question. However with an answer someone else might find this useful.

This function tries to grab a value from a cell

if the cell has a SharedStringValue it will return that or if its just a number

Or return " " if no value

public static string GetCellV(Cell cell, SharedStringTable ss)
    {
        string cellV = null;

        try
        {
            cellV = cell.CellValue.InnerText;
            if (cell.DataType != null
              && cell.DataType.Value == CellValues.SharedString)
            {
                cellV = ss.ElementAt(Int32.Parse(cellV)).InnerText;
            }
            else
            {

                cellV = cell.CellValue.InnerText;
            }
        }
        catch (Exception)
        {
            cellV = " ";
        }

        return cellV;
    }

Im sure you could edit the last part for your needs.

NOTE:

Interop is not very resourceful and is really slow at executing, watch out for Excel processes that aren't closed once you've finished executing.

Open XML is much faster as it directly edits the XML code.

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