Parse colors used in Word document, use as backcolor for ListViewItem - wrong color

怎甘沉沦 提交于 2021-01-29 04:51:18

问题


I'm trying to list all font colors used in a Word document, display them as colored ListViewItems.

I can parse the doc and get all unique font colors.

What does not work? - Getting the ListViewItems in the correct color. Grey35 appears as yellow, green as dark green.

Here are my active code sections for that

var maxnum = doc.Words.Count;
var ind = 0;
foreach (Word.Range wd in doc.Content.Words)
{
    if (!string.IsNullOrEmpty(wd.Text.Trim('\r', '\n', ' ')))
    {
        ind++;
        bkwParseColors.ReportProgress(100*ind/maxnum, wd.Font.Color);
    }
}

And here's what I do with it:

private void bkwParseColors_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage;
    var color = (Word.WdColor)e.UserState;
    var drin = lstColors.FindItemWithText(color.GetHashCode().ToString());
    if(drin==null)
    {
        var li = new ListViewItem(color.GetHashCode().ToString());
        li.BackColor = ColorTranslator.FromOle((int) color);
        lstColors.Items.Add(li);
    }
}

Alas, instead of grey, I get yellow, instead of Word's green I get a dark, full green and instead of a light grey I get a dark 50% grey (at least much darker). The only correct color is black.

During debugging I also found that the first grey, which translates to yellow in the ListView is listed as wdWhite. :-??

It almost looks like I am only getting "full colors" with some value (lightness) missing. Can someone tell me how to get the correct color?

Using Word 2010, VS Community 2013, Framework 4.0.

Edit: I seem to be getting closer!

==> The behavior is different depending on whether I have colored the text using "theme colors" that come up directly when clicking text color, or whether I click "More colors" and then pick one from the color wheel! If I color text from the color wheel, I seem to be getting the correct value, including grey. If I use the grey from the default palette that comes up first, grey is denoted as "White, Background 1, darker xx%", which would explain the wdWhite.

Unfortunately, this is meant for docs that already contain colored text and the coloring is not under my control. So I need a way to include "theme colors" into this.

Edit2: It looks as though the answer to my question lies here: Office 2007 [and higher] interop: retrieve RGB-color Or basically in the page linked there: http://www.wordarticles.com/Articles/Colours/2007.php#UIConsiderations

I will work myself through this in the hope to be getting correct color values from theme colors.


回答1:


Got a satisfying result now. What I first did was

  1. use the RgbColorRetriever class by pkuderov as linked in the accepted answer to this thread: Office 2007 [and higher] interop: retrieve RGB-color
  2. Since the resulting system color was slightly darker than the Word color, I additionally applied a lightening effect as proposed by Pavel Vladov in this thread (second answer, not the accepted one): C#: Create a lighter/darker color based on a system color

Edit Alas, this does not seem to work for certain theme grays. However I need it to also work with these.

Therefore: alternative solution using Open XML SDK:

private void bkwParseColors_DoWork(object sender, DoWorkEventArgs e)
{
    var docItem = (string) e.Argument;
    using (var docx = WordprocessingDocument.Open(docItem, false))
    {
        var ind = 0;
        var maxnum = docx.MainDocumentPart.Document.Descendants<Run>().Count();
        foreach (Run rText in docx.MainDocumentPart.Document.Descendants<Run>())
        {
            if (rText.RunProperties != null)
            {
                if (rText.RunProperties.Color != null)
                {
                    ind++;
                    bkwParseColors.ReportProgress(100*ind/maxnum, rText.RunProperties.Color);
                }
            }
        }
    }
}

Progress change method for creating ListViewItem in correct color and storing Word color value as well as theme color:

private void bkwParseColors_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage;

    var color = (DocumentFormat.OpenXml.Wordprocessing.Color)e.UserState;
    var thema = "";
    if (color.ThemeColor!=null)
        thema = color.ThemeColor.Value.ToString();

    var farbe = color.Val.Value; //hex RGB
    var drin = lstColors.FindItemWithText(farbe);
    if(drin==null)
    {
        var li = new myListItem
        {
            Design = thema,
            Farbe = farbe,
            Text = farbe,
            BackColor = ColorTranslator.FromHtml("#" + farbe)
        };
        lstColors.Items.Add(li);
    }
}

Some additional info: I needed all this because I need to hide/unhide text of a certain color, but that color is never certain, i.e. depends on the whims of the customer and/or the colors already used in the document...

So for completions sake, here is how I hide all text in the document except for text in the selected color:

private void bkwEinblenden_DoWork(object sender, DoWorkEventArgs e)
{
    var args = (List<object>) e.Argument;
    var pfad = (string) args[0];
    var color = (myListItem) args[1];
    using (var docx = WordprocessingDocument.Open(pfad, true))
    {
        var ind = 0;
        var maxnum = docx.MainDocumentPart.Document.Descendants<Run>().Count();
        foreach (Run rText in docx.MainDocumentPart.Document.Descendants<Run>())
        {
            bkwEinblenden.ReportProgress(100*ind/maxnum);
            var vanish = new Vanish() { Val = OnOffValue.FromBoolean(true) };
            if (rText.RunProperties == null)
            {
                var runProp = new RunProperties {Vanish = vanish};
                rText.RunProperties = runProp;
            }
            else
            {
                if (rText.RunProperties.Vanish == null)
                    rText.RunProperties.Vanish = vanish;
                else
                {
                    rText.RunProperties.Vanish.Val = OnOffValue.FromBoolean(true);
                }
            }
            if (rText.RunProperties.Color != null)
            {
                if (rText.RunProperties.Color.Val == color.Farbe)
                {
                    if (!string.IsNullOrEmpty(color.Design))
                    {
                        if (rText.RunProperties.Color.ThemeColor.Value.ToString() == color.Design)
                        {
                            rText.RunProperties.Vanish.Val = OnOffValue.FromBoolean(false);
                        }
                    }
                    else
                    {
                        rText.RunProperties.Vanish.Val = OnOffValue.FromBoolean(false);
                    }
                }
            }
        }
    }
}


来源:https://stackoverflow.com/questions/33569480/parse-colors-used-in-word-document-use-as-backcolor-for-listviewitem-wrong-co

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!