2016-08-18 7 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; 
    } 
} 

Я использую Interop потому что я считаю, что гораздо проще работать, а также потому, что я не мог найти достойный пример того, как сделать это с OpenXML. Однако я знаю, что Excel имеет свои пределы, когда дело доходит до текста ячейки, поэтому я открыт для предложений.

Есть ли способ раскрасить отдельные слова в ячейке, содержащей> 255 символов, используя Interop?

Если все не удастся, мне, вероятно, придется создать документ Word со столом, сделать там форматирование, а затем скопировать/вставить в Excel (yukk). Пожалуйста, помогите мне избежать этого уродства.

P.S: Да, резюме ревизии должно быть основано на Excel.

+0

Попробуйте использовать cell.Value вместо cell.Text. По крайней мере, в EPPlus текст - это значение, отображаемое для пользователя, а Value - содержимое ячейки. Итак, если ширина столбца меньше содержимого, свойство Text имеет другое значение, чем свойство Value. – Magnetron

+0

Нет. Символы не имеют свойства Value. – LocEngineer

+0

@ Магнетрон, извините, был немного толст. Конечно, я могу использовать '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" }); 
    } 
} 

И мой метод XlHelper.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, делают это намного проще и содержат примеры стилей –