Is there a way to preserve text formatting in Excel when extracting it from the worksheet with C# and storing the values into strings?

StackOverflow https://stackoverflow.com/questions/17728608

Question

What I'm Trying to Do:

I am reading in cell values in an Excel worksheet, and the text often has special formatting such as superscript and subscript. I would like to preserve this formatting when bringing it into my C# application, using the strings for various labels and such. However, with my current implementation, all superscript and subscript characters lose that formatting. I believe it has to do with the fact that I cast things to different types throughout the process:

        const string fileName = "C:\\Users\\J.Smith\\Desktop\\FeatureInfoPropertyAttributesEXCEL.xlsx";

        // Prepare the required items
        Workbook wb = null;

        // Start Excel
        Application excel = new Application {Visible = false};

        try
        {
            // Open file
            Workbook wb = excel.Workbooks.Open(fileName);

            // Read sheets
            Sheets sheets = wb.Worksheets;

            // Select sheet
            Worksheet ws = (Worksheet) sheets.Item["FeatureInfoPropertyAttributes"];

            string firstCellForPropertiesRange = "A2";
            string secondCellForPropertiesRange = ws.Range[firstCellForPropertiesRange].End[XlDirection.xlDown].Address;
            string firstCellForHeadersRange = firstCellForPropertiesRange.Replace("A", "B");
            string secondCellForHeadersRange = secondCellForPropertiesRange.Replace("A", "B");
            string firstCellForProposedHeadersRange1 = firstCellForHeadersRange.Replace("B", "C");
            string secondCellForProposedHeadersRange1 = secondCellForHeadersRange.Replace("B", "C");
            string firstCellForProposedHeadersRange2 = firstCellForProposedHeadersRange1.Replace("C", "D");
            string secondCellForProposedHeadersRange2 = secondCellForProposedHeadersRange1.Replace("C", "D");

            Range propertiesRange = ws.Range[firstCellForPropertiesRange, secondCellForPropertiesRange];
            Range headersRange = ws.Range[firstCellForHeadersRange, secondCellForHeadersRange];
            Range proposedHeadersRange1 = ws.Range[firstCellForProposedHeadersRange1, secondCellForProposedHeadersRange1];
            Range proposedHeadersRange2 =
                ws.Range[firstCellForProposedHeadersRange2, secondCellForProposedHeadersRange2];

            List<string> properties =
                propertiesRange.Cells.Cast<object>()
                               .Select((t, i) => ((Range) propertiesRange.Cells[i + 1]).Value2 ?? string.Empty)
                               .Cast<string>()
                               .ToList();
            List<string> existingHeaders =
                headersRange.Cells.Cast<object>()
                            .Select((t, i) => ((Range) headersRange.Cells[i + 1]).Value2 ?? string.Empty)
                            .Cast<string>()
                            .ToList();

            List<string> proposedHeaders1 =
                proposedHeadersRange1.Cells.Cast<object>()
                                     .Select(
                                         (t, i) =>
                                         ((Range) proposedHeadersRange1.Cells[i + 1]).Value2 ?? string.Empty)
                                     .Cast<string>()
                                     .ToList();

            List<string> proposedHeaders2 =
                proposedHeadersRange2.Cells.Cast<object>()
                                     .Select(
                                         (t, i) =>
                                         ((Range)proposedHeadersRange2.Cells[i + 1]).Value2 ?? string.Empty)
                                     .Cast<string>()
                                     .ToList();

            foreach (string s in proposedHeaders1.Where(s => !s.Equals(string.Empty)))
            {
                Console.WriteLine(s);
            }

            foreach (string s in proposedHeaders2.Where(s => !s.Equals(string.Empty)))
            {
                Console.WriteLine(s);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
        finally
        {
            excel.Visible = true;
            wb.Close(false, null, null);
            excel.Quit();
        }

First Question:

Does C# strings support such formatting characteristics as superscript and subscript in strings?

Second Question:

If the answer to the first question is 'yes', how would I go about accomplishing this?

Update: Example of a hard coded string with superscript formatting

enter image description here

Was it helpful?

Solution

You can get the superscript/subscript information from Excel via the logical flags in the Font Property of the given Range:

Range curRange = ws.get_Range("A1");
if(curRange.Font.Superscript)
{
    //It is a superscript
}
if(curRange.Font.Subscript)
{
    //It is a subscript
}

The easiest way to represent this in C# winforms is relying on a RichTextBox (you can even make it "look like a label", as suggested in the following link) and on its SelectionCharOffset. With Labels, it is not so straightforward but there are some workarounds.

---------- UPDATE

ANSWER TO THE FIRST QUESTION:

C# supports formatting through its Objects, not its string type. Excel strings do not support formatting either; the Ranges are the ones in charge of dealing with this.

ANSWER TO THE SECOND QUESTION:

You can replicate in C# what Excel Cells/Ranges do by relying on the corresponding C# equivalent, that is: Controls/Objects. The Control meant for text-decoration is the RichTextBox and thus it is the best equivalent in this case. Nonetheless, there are different ways to deliver the result you want by using other Controls, as explained above.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top