2016-08-18 62 views
4

我已經爲第三方sw編寫了一個插件,該插件將修訂後的文本提取到Excel工作表中,然後在Excel中爲更改後的部分着色。 只要每個文本段(=單元格內容)不超過255個字符,它都可以工作。唉,這可以並偶爾會發生。Excel中的彩色文本部分> 255個字符

爲了識別Excel中已更改的零件,我將它們與<del>和其他零件包圍在一起。 <add>用於刪除和添加文本的標籤。然後我色這些部件(以及去除環境標籤)是這樣的:

while (((string)cell1.Text).Contains("<del>")) 
{ 
    try 
    { 
     var pos = ((string) cell1.Text).IndexOf("<del>") + 1; 
     var pos2 = ((string) cell1.Text).IndexOf("</del>") + 1; 
     var txt = cell1.Characters[pos, (pos2-pos) + 9].Text; 

     txt = txt.Replace("<del>", "").Replace("</del>", ""); 
     cell1.Characters[pos, (pos2-pos) + 9].Text = txt; 
     cell1.Characters[pos, txt.Length-3].Font.Color = -16776961; 
    } 
    catch 
    { 
      break; 
    } 
} 

我使用的互操作性,因爲我覺得它更容易與工作,而且還因爲我無法找到如何做任何像樣的例子這與OpenXML。但是我知道Excel在單元格文本方面有其侷限性,所以我願意提供建議。

有沒有辦法使用Interop在包含> 255個字符的單元格中對單個單詞進行着色?

如果一切都失敗了,我可能不得不用表格創建一個Word文檔,在那裏進行格式化,然後複製/粘貼到Excel(yukk)。請幫我避免這個醜陋。

P.S:是的,修訂摘要需要基於Excel。

+0

嘗試使用cell.Value而不是cell.Text。至少在EPPlus中,文本是爲用戶顯示的值,而值是單元格的內容。因此,如果列寬小於內容,那麼Text屬性會包含與Value屬性不同的值。 – Magnetron

+0

不行。字符沒有Value屬性。 – LocEngineer

+0

@Magnetron對不起,在那裏有點厚。當然,我可以使用'cell.Value'。雖然沒有任何區別。對於單元格> 255仍然沒有結果。 – LocEngineer

回答

0

好的,我現在用OpenXML解決了它。 如果一個單元格包含要着色的文本,我將創建一個文本到該位置的文本,第二個包含受影響文本的彩色運行以及第三個包含其餘文本的默認運行。

var xlsx = SpreadsheetDocument.Open(xlsPath, true); 
var contents = xlsx.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First(); 
foreach (SharedStringItem si in contents.SharedStringTable.Elements<SharedStringItem>()) 
{ 
    if (si.Text != null) 
    { 
     XlHelper.ColorCellText(si, "del", new DocumentFormat.OpenXml.Spreadsheet.Color { Rgb = "FFFF0000" }); 
     XlHelper.ColorCellText(si, "add", new DocumentFormat.OpenXml.Spreadsheet.Color { Rgb = "0000BF00" }); 
    } 
} 

而且我X​​lHelper.ColorCellText方法:

public static void ColorCellText(SharedStringItem si, string TagName, DocumentFormat.OpenXml.Spreadsheet.Color col) 
{ 
    var newText = si.InnerText; 
    var startTag = string.Format("<{0}>", TagName); 
    var endTag = string.Format("</{0}>", TagName); 
    if (newText.Contains(startTag)) 
    { 
     si.Text.Remove(); 
     var lastpos = 0; 
     while (newText.Contains(startTag)) 
     { 
      try 
      { 
       var pos1 = newText.IndexOf(startTag); 
       var pos2 = newText.IndexOf(endTag); 
       var txtLen = pos2 - pos1 - 5; 
       var it = string.Concat(newText.Substring(0, pos1), newText.Substring(pos1 + 5, txtLen), 
        newText.Substring(pos2 + 6)); 

       var run = new Run(); 
       var txt = new Text 
       { 
        Text = it.Substring(0, pos1), 
        Space = SpaceProcessingModeValues.Preserve 
       }; 
       run.Append(txt); 
       si.Append(run); 

       run = new Run(); 
       txt = new Text 
       { 
        Text = it.Substring(pos1, txtLen), 
        Space = SpaceProcessingModeValues.Preserve 
       }; 

       var rp = new RunProperties(); 

       rp.Append(col.CloneNode(true)); 
       run.RunProperties = rp; 
       run.Append(txt.CloneNode(true)); 
       si.Append(run.CloneNode(true)); 

       newText = newText.Substring(pos2 + 6); 
      } 
      catch(Exception ex) 
      { 
       using (var sw = new StreamWriter(logFile, true)) 
       { 
        sw.WriteLine("Error: {0}\r\n{1}", ex.Message, newText); 
       } 
       break; 
      } 
     } 
     if (newText.Length>=0) 
     { 
      var lastrun = new Run(); 
      var lasttxt = new Text 
      { 
       Text = newText, 
       Space = SpaceProcessingModeValues.Preserve 
      }; 
      lastrun.Append(lasttxt); 
      si.Append(lastrun); 
     } 
    } 
} 

Space = SpaceProcessingModeValues.Preserve部分是這裏的關鍵,ALS否則將所有三個部分粘合起來並關閉之間的空間。

我想我會研究這個EPPlus,因爲它的「In-cell Richtext」功能聽起來很有前途。

+0

OpenXML文檔並不糟糕,它的級別較低,您必須瞭解Excel的模型 - 單元格具有樣式。就像您可以在使用Excel時應用樣式一樣,您可以使用SDK應用樣式。您不需要實際修改*文本*。像EPPlus這樣的更高級的庫使得這更容易並且包含樣式示例 –