none
C# и Word - работа с таблицей

    Вопрос

  • Учусь работать с Word с помощью C#. В программе
    namespace CsWordCons
    {
      class Program
      {
        static void Main(string[] args)
        {
          Object missing = System.Reflection.Missing.Value;
          Object confConv = false;
          Object readOnly = true;
          Object isVisible = false;
          Object saveChanges = false;
          Object filename = @"d:\MyProgramming\CsWordCons\Документ 1.doc";
          //Object filename = @"d:\MyProgramming\CsWordCons\Документ 1.docx";
          Word.Application word = new Word.Application();
          Word.Document doc = new Word.Document();
          doc = word.Documents.Open(ref filename, ref confConv, ref readOnly);
          word.Visible = false; 
          Word.Table tbl = doc.Tables[1];
          string [] strArr = new string [tbl.Rows.Count - 1];
          for(int i = 1; i < tbl.Rows.Count; i++)
          {
            //strArr[i] = (string)  tbl.Cell(i, 4); 
            Console.WriteLine(tbl.Cell(i, 4));
          }
          doc.Close(ref saveChanges);
          word.Quit(ref saveChanges);
          Console.ReadKey();
             
        } // Main
      } //class Program
    } // namespace CsWordCons

    хотел бы получить в определенной колонке строковое значение ячеек и сохранить их в массив строк. К сожалению,не нашел нужного метода преобразования значения ячейки в строку. Кроме того, В фрагменте кода
    doc.Close(ref saveChanges);
    word.Quit(ref saveChanges);
    получаю предупреждения:
    Warning 1 Ambiguity between method 'Microsoft.Office.Interop.Word._Document.Close(ref object, ref object, ref object)' and non-method 'Microsoft.Office.Interop.Word.DocumentEvents2_Event.Close'. Using method group.
    Warning 2 Ambiguity between method 'Microsoft.Office.Interop.Word._Application.Quit(ref object, ref object, ref object)' and non-method 'Microsoft.Office.Interop.Word.ApplicationEvents4_Event.Quit'. Using method group.
    Предупреждение, как я понял, о неоднозначности метода Close (Quit) и не метода Close (Quit). Как изменить этот код, чтобы предупреждения не возникали?

    Alex

    12 апреля 2018 г. 16:06

Ответы

  • "К сожалению,не нашел нужного метода преобразования значения ячейки в строку"

    Word.Range range = tbl.Cell(i, 1).Range;
    Console.WriteLine(range.Text);

    "Как изменить этот код, чтобы предупреждения не возникали?"

    ((Word._Document)doc).Close();
    ((Word._Application)word).Quit();



    • Изменено VadimTagil 13 апреля 2018 г. 5:42
    • Помечено в качестве ответа tumanovalex 13 апреля 2018 г. 9:41
    13 апреля 2018 г. 5:41
  • А да, забыл про популярные грабли - текст в ячейках вордовской таблицы содержит управляющие символы, которые могут испортить вывод в консоль (возврат каретки) и сравнение строк. Чтобы нормально работать со строками, нужно от них избавиться:

                string find = "example";
                
                for (int i = 1; i <= numRows; i++)
                {
                    for (int j = 1; j <= numCols; j++)
                    {
                        try
                        {
                            string text = tbl.Cell(i, j).Range.Text;
                            text = text.Replace("\r", "");
                            text = text.Replace("\a", "");
                            Console.Write("(" + i.ToString() + "-" + j.ToString() + "): " + text);
                            if (find == text) Console.Write(" - Found");
                            Console.WriteLine();
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.ToString());
                        }
                    } 
                }

    • Помечено в качестве ответа tumanovalex 20 апреля 2018 г. 7:37
    20 апреля 2018 г. 3:17
  • Перемещаться просто - у таблицы есть свойство Rows, по которому можно пройти foreach. У Row соответственно, брать свойство Cells (ну или начинать с первой ячейки и дальше переходить, пользуясь свойством Cell.Next).

    По второму, как ни странно, нормально способа нет. Читайте здесь, много понаписано на эту тему: https://ru.stackoverflow.com/q/805934/240512

    • Помечено в качестве ответа tumanovalex 25 апреля 2018 г. 17:53
    23 апреля 2018 г. 18:51
  • А как с помощью foreach перемещаться по строкам?   foreach(tbl.Rows in tbl), естественно, дает ошибку, а как правильно?

    Alex

    • Помечено в качестве ответа tumanovalex 25 апреля 2018 г. 18:25
    25 апреля 2018 г. 17:59

Все ответы

  • "К сожалению,не нашел нужного метода преобразования значения ячейки в строку"

    Word.Range range = tbl.Cell(i, 1).Range;
    Console.WriteLine(range.Text);

    "Как изменить этот код, чтобы предупреждения не возникали?"

    ((Word._Document)doc).Close();
    ((Word._Application)word).Quit();



    • Изменено VadimTagil 13 апреля 2018 г. 5:42
    • Помечено в качестве ответа tumanovalex 13 апреля 2018 г. 9:41
    13 апреля 2018 г. 5:41
  • Спасибо большое!

    Alex

    13 апреля 2018 г. 9:42
  • Visual Studio 2012, Windows 7. В программе
    using System;
    using System.Configuration;
    using Word = Microsoft.Office.Interop.Word;
    using System.Collections.Generic;
    
    namespace CsWordCons
    {
      class Program
      {
        static void FindString()
        {
          List<string> strArrFind = new List<string> {"111111", "222222", "33333"};
          Object missing = System.Reflection.Missing.Value;
          Object confConv = false;
          Object readOnly = true;
          Object isVisible = false;
          Object saveChanges = false;
          Word.Application word = new Word.Application();
          Word.Document doc = new Word.Document();
          word.Visible = false;
          Word.Table tbl = null;
          Object filename = Environment.CurrentDirectory + "\\Документ 1.docx";
          Console.WriteLine(filename);
          doc = word.Documents.Open(ref filename, ref confConv, ref readOnly);
          try
          {
            tbl = doc.Tables[1];
          }
          catch (Exception ex)
          {
            tbl = null;
            Console.WriteLine("\nВ документе " + filename.ToString() + " нет таблиц!\n");
            Console.ReadKey();
            Environment.Exit(1);
          }
          int numCols = tbl.Columns.Count, numRows = tbl.Rows.Count;
          foreach (string strFind in strArrFind)
          {
            Console.WriteLine("************* Строка для поиска: {0} *************", strFind);
            for (int i = 2; i <= numRows; i++)
            {
              for (int j = 3; j <= numCols; j++)
              {
                Console.WriteLine(tbl.Cell(i, j).Range.Text);
                Console.WriteLine(tbl.Cell(i, j).Range.Text + "  " + strFind);
                if (tbl.Cell(i, j).Range.Text == strFind)
                {
                  Console.WriteLine(strFind + "  " + i.ToString() + ", " + j.ToString());
                }
                Console.WriteLine("---------------------------------------");
              } // for j
            } // for i
          } // foreach
          ((Word._Document)doc).Close(ref saveChanges, missing, missing);
          ((Word._Application)word).Quit(ref saveChanges);
        } // FindString()
    
        static void Main(string[] args)
        {
          FindString();
          Console.ReadKey();
        } // Main
      } //class Program
    } // namespace CsWordConsвозникают следующие ошибки:
    1. Вывод в консоль Console.WriteLine(tbl.Cell(i, j).Range.Text + "  " + strFind); должен, как я понимаю, вывести текст из ячейки таблицы, затем пробелы, затем  поисковую строку. На самом деле пропадает строка tbl.Cell(i, j).Range.Text и выводится только сдвинутая поисковая строка.
    2. Условие tbl.Cell(i, j).Range.Text == strFind никогда не выполняется (при установке в теле условия точки прерывания захода в тело условия нет).
    Помогите, пожалуйста, исправить ошибки. 

    Alex

    19 апреля 2018 г. 12:06
  • А да, забыл про популярные грабли - текст в ячейках вордовской таблицы содержит управляющие символы, которые могут испортить вывод в консоль (возврат каретки) и сравнение строк. Чтобы нормально работать со строками, нужно от них избавиться:

                string find = "example";
                
                for (int i = 1; i <= numRows; i++)
                {
                    for (int j = 1; j <= numCols; j++)
                    {
                        try
                        {
                            string text = tbl.Cell(i, j).Range.Text;
                            text = text.Replace("\r", "");
                            text = text.Replace("\a", "");
                            Console.Write("(" + i.ToString() + "-" + j.ToString() + "): " + text);
                            if (find == text) Console.Write(" - Found");
                            Console.WriteLine();
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.ToString());
                        }
                    } 
                }

    • Помечено в качестве ответа tumanovalex 20 апреля 2018 г. 7:37
    20 апреля 2018 г. 3:17
  • Программа
    using System;
    using System.Configuration;
    using Word = Microsoft.Office.Interop.Word;
    using System.Collections.Generic;
    using System.IO;
    using System.Configuration;
    
    namespace CsWordCons
    {
      class Program
      {
    
        static void GetFindString(int numRowBegin, int numCol)
        {
          string cyrDir = Environment.CurrentDirectory;
          string[] strDocFileName = Directory.GetFiles(cyrDir, "*.do*", SearchOption.AllDirectories);
          if (strDocFileName.Length > 1)
          {
            Console.WriteLine("Рядом с программой должен быть один файл с расширением doc или docx!");
            Console.ReadKey();
            Environment.Exit(1);
          }
          Object missing = System.Reflection.Missing.Value;
          Object confConv = false;
          Object readOnly = true;
          Object isVisible = false;
          Object saveChanges = false;
          Object filename = strDocFileName[0];
          Word.Application word = new Word.Application();
          Word.Document doc = new Word.Document();
          doc = word.Documents.Open(ref filename, ref confConv, ref readOnly);
          word.Visible = false;
          Word.Table tbl = null;
          try
          {
            tbl = doc.Tables[1];
          }
          catch (Exception ex)
          {
            Console.WriteLine("В документе " + strDocFileName[0] + " нет таблиц!");
            ((Word._Document)doc).Close(ref saveChanges, missing, missing);
            ((Word._Application)word).Quit(ref saveChanges);
            Console.ReadKey();
            Environment.Exit(1);
          }
          int numRows = tbl.Rows.Count;
          List<string> strListFind = new List<string>();
          for (int i = numRowBegin; i <= numRows; i++)
          {
            string[] strOnlyFind = tbl.Cell(i, numCol).Range.Text.Split('\r');
            foreach (string str in strOnlyFind)
            {
              if (str.Length > 2)
                strListFind.Add(str.Trim());
            }
          }
          Console.WriteLine("Будет проведен поиск следующих серийных номеров:");
          foreach (string str in strListFind)
            Console.WriteLine(str);
          Console.WriteLine("---------------------------------------------");
          Console.WriteLine("Нажмите любую клавишу для поиска.\nЕсли серийные номера определены неправильно - проверьте\n" +
                             "данные в конфигурационном файле");
          Console.ReadKey();
          ((Word._Document)doc).Close(ref saveChanges, missing, missing);
          ((Word._Application)word).Quit(ref saveChanges);
        } // GetFindString
    
        static void Main(string[] args)
        {
          Configuration config = ConfigurationManager.OpenExeConfiguration("CsWordCons.exe");
          string[] allKeys = config.AppSettings.Settings.AllKeys;
          int numKeys = allKeys.Length;
          string strNumRowBegin = config.AppSettings.Settings[allKeys[0]].Value;
          string strNumCol = config.AppSettings.Settings[allKeys[1]].Value;
          string strResultFileName = config.AppSettings.Settings[allKeys[numKeys - 1]].Value;
          GetFindString(int.Parse(strNumRowBegin), int.Parse(strNumCol));
          Console.ReadKey();
        } // Main
      } //class Program
    } // namespace CsWordCons
    нормально работает, если в таблице нет строк с объединенными ячейками. Если они есть, то в строке string[] strOnlyFind = tbl.Cell(i, numCol).Range.Text.Split('\r'); - ошибка. Подскажите, пожалуйста, как:
    - перемещаться по строкам таблицы;
    - определить, что в строке объединены ячейки. Проект разместил на https://yadi.sk/d/ro0TtAzV3Uh6Fj

    Alex

    23 апреля 2018 г. 18:20
  • Перемещаться просто - у таблицы есть свойство Rows, по которому можно пройти foreach. У Row соответственно, брать свойство Cells (ну или начинать с первой ячейки и дальше переходить, пользуясь свойством Cell.Next).

    По второму, как ни странно, нормально способа нет. Читайте здесь, много понаписано на эту тему: https://ru.stackoverflow.com/q/805934/240512

    • Помечено в качестве ответа tumanovalex 25 апреля 2018 г. 17:53
    23 апреля 2018 г. 18:51
  • А как с помощью foreach перемещаться по строкам?   foreach(tbl.Rows in tbl), естественно, дает ошибку, а как правильно?

    Alex

    • Помечено в качестве ответа tumanovalex 25 апреля 2018 г. 18:25
    25 апреля 2018 г. 17:59
  • foreach(var rTable in tbl.Rows) ошибки не дает, но не понятно, что с этим делать. Было бы здорово, если бы можно было определить количество ячеек в rTable, но rTable нет нужного метода.

    Alex

    25 апреля 2018 г. 18:26
  • У Row есть свойство Cells, которое и позволяет получить все ячейки. Смотрите в документации
    26 апреля 2018 г. 3:02