Работа с ревизиями Word из С++
От: paharelau  
Дата: 13.01.03 14:46
Оценка:
Привет всем!

Вопрос может не совсем в тему, но я не знаю куда обратиться. Дело в следующем. Пытаюсь из Visual C++ сравнивать Word документы. В принципе, все нормальнло, до тех пор пока не надо работать с коллекциями ревизий (Word::RevisionsPtr). А тут-то и наступает темная ночь. Как нормально пройтись по этой коллекии.
Вариант 1:


...

Word::RevisionPtr spRevisions =...;
long lCount = spRevision->GetCount();

for(long it = 1L; it<=lCount; it++)
{
   Word::RevisionPtr = spRevisions->Item(it)
   ...
}

...


Полная задница!!!

Во-первых, если ревизий много — работает очень медленно!!!(Очень!!!). Во-вторых, на Word 2000 количество может быть, к примеру, 10, а реально в коллекции 4-5 ревизий, причем с абсолютно рандомными индексами!
При попытке взять ревизию может просто крахнуться.

Вариант 2:


 Word::_DocumentPtr doc = ...;
    IUnknownPtr spUnk = doc->Revisions->Get_NewEnum();
    CComQIPtr<IEnumVARIANT, &IID_IEnumVARIANT> pNewEnum = spUnk;
    Word::RevisionPtr spRevision;
    VARIANT varRev;
    ::VariantInit(&varRev);
    while (pNewEnum->Next(1, &varRev, NULL) == S_OK) 
    {
        ASSERT (varRev.vt == VT_DISPATCH);
        spRevision = varRev.pdispVal; 
        ::VariantClear(&varRev); 

        ...
    }



В принципе это работает, пока не сравниваются 2 абсолютно разных документа. Иначе на Word XP входит в бесконечный цикл.

Вопрос, может кто сталкивался с работой с ревизиями. Буду благодарен любым идеям и предложениям.

Re: Работа с ревизиями Word из С++
От: Tom Россия http://www.RSDN.ru
Дата: 13.01.03 15:18
Оценка:
Здравствуйте, paharelau, Вы писали:

P>Привет всем!


P>Вопрос может не совсем в тему, но я не знаю куда обратиться. Дело в следующем. Пытаюсь из Visual C++ сравнивать Word документы. В принципе, все нормальнло, до тех пор пока не надо работать с коллекциями ревизий (Word::RevisionsPtr). А тут-то и наступает темная ночь. Как нормально пройтись по этой коллекии.

P>Вариант 1:

P>

P>
P>...

P>Word::RevisionPtr spRevisions =...;
P>long lCount = spRevision->GetCount();

P>for(long it = 1L; it<=lCount; it++)
P>{
P>   Word::RevisionPtr = spRevisions->Item(it)
P>   ...
P>}

P>...
P>


P>Полная задница!!!


P>Во-первых, если ревизий много — работает очень медленно!!!(Очень!!!). Во-вторых, на Word 2000 количество может быть, к примеру, 10, а реально в коллекции 4-5 ревизий, причем с абсолютно рандомными индексами!

P>При попытке взять ревизию может просто крахнуться.

P>Вариант 2:


P>

P>
P> Word::_DocumentPtr doc = ...;
P>    IUnknownPtr spUnk = doc->Revisions->Get_NewEnum();
P>    CComQIPtr<IEnumVARIANT, &IID_IEnumVARIANT> pNewEnum = spUnk;
P>    Word::RevisionPtr spRevision;
P>    VARIANT varRev;
P>    ::VariantInit(&varRev);
P>    while (pNewEnum->Next(1, &varRev, NULL) == S_OK) 
P>    {
P>        ASSERT (varRev.vt == VT_DISPATCH);
P>        spRevision = varRev.pdispVal; 
P>        ::VariantClear(&varRev); 

P>        ...
P>    }
P>


P>

P>В принципе это работает, пока не сравниваются 2 абсолютно разных документа. Иначе на Word XP входит в бесконечный цикл.

P>Вопрос, может кто сталкивался с работой с ревизиями. Буду благодарен любым идеям и предложениям.


P>


А почему бы тебе в методе Next получать не по одному елементу, а целый массив ? И проверять надо на S_FALSE.
Народная мудрось
всем все никому ничего(с).
Re[2]: Работа с ревизиями Word из С++
От: paharelau  
Дата: 13.01.03 15:28
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>Здравствуйте, paharelau, Вы писали:


P>>Привет всем!


P>>Вопрос может не совсем в тему, но я не знаю куда обратиться. Дело в следующем. Пытаюсь из Visual C++ сравнивать Word документы. В принципе, все нормальнло, до тех пор пока не надо работать с коллекциями ревизий (Word::RevisionsPtr). А тут-то и наступает темная ночь. Как нормально пройтись по этой коллекии.

P>>Вариант 1:

P>>

P>>
P>>...

P>>Word::RevisionPtr spRevisions =...;
P>>long lCount = spRevision->GetCount();

P>>for(long it = 1L; it<=lCount; it++)
P>>{
P>>   Word::RevisionPtr = spRevisions->Item(it)
P>>   ...
P>>}

P>>...
P>>


P>>Полная задница!!!


P>>Во-первых, если ревизий много — работает очень медленно!!!(Очень!!!). Во-вторых, на Word 2000 количество может быть, к примеру, 10, а реально в коллекции 4-5 ревизий, причем с абсолютно рандомными индексами!

P>>При попытке взять ревизию может просто крахнуться.

P>>Вариант 2:


P>>

P>>
P>> Word::_DocumentPtr doc = ...;
P>>    IUnknownPtr spUnk = doc->Revisions->Get_NewEnum();
P>>    CComQIPtr<IEnumVARIANT, &IID_IEnumVARIANT> pNewEnum = spUnk;
P>>    Word::RevisionPtr spRevision;
P>>    VARIANT varRev;
P>>    ::VariantInit(&varRev);
P>>    while (pNewEnum->Next(1, &varRev, NULL) == S_OK) 
P>>    {
P>>        ASSERT (varRev.vt == VT_DISPATCH);
P>>        spRevision = varRev.pdispVal; 
P>>        ::VariantClear(&varRev); 

P>>        ...
P>>    }
P>>


P>>

P>>В принципе это работает, пока не сравниваются 2 абсолютно разных документа. Иначе на Word XP входит в бесконечный цикл.

P>>Вопрос, может кто сталкивался с работой с ревизиями. Буду благодарен любым идеям и предложениям.


P>>


Tom>А почему бы тебе в методе Next получать не по одному елементу, а целый массив ? И проверять надо на S_FALSE.



Можно пример кода?
Re[3]: Работа с ревизиями Word из С++
От: Tom Россия http://www.RSDN.ru
Дата: 13.01.03 15:56
Оценка:
P>Можно пример кода?

Примерно так, но я ессно не компилировал
VARIANT varRev[12345];
ULONG celtFetched;
HRESULT hr;

//Тут проинициализировать весь массив вариантов
do 
{
    celtFetched = 0; //Обнулить на всякий случай
    hr = pNewEnum->Next(12345, &varRev, &celtFetched);
   
    if ((hr = S_OK) && (celtFetched))
    {
        //тут проверяй свои елементы массива,
        //только столько членов, сколько вернулось в celtFetched
    }
} while (celtFetched)
Народная мудрось
всем все никому ничего(с).
Re[4]: В догонку
От: Tom Россия http://www.RSDN.ru
Дата: 13.01.03 16:03
Оценка:
Блинн. Про S_FALSE забыл. Так что замени в if && на ||
Народная мудрось
всем все никому ничего(с).
Re[4]: Работа с ревизиями Word из С++
От: paharelau  
Дата: 13.01.03 16:32
Оценка:
Здравствуйте, Tom, Вы писали:

P>>Можно пример кода?


Tom>Примерно так, но я ессно не компилировал

Tom>
Tom>VARIANT varRev[12345];
Tom>ULONG celtFetched;
Tom>HRESULT hr;

Tom>//Тут проинициализировать весь массив вариантов
Tom>do 
Tom>{
Tom>    celtFetched = 0; //Обнулить на всякий случай
Tom>    hr = pNewEnum->Next(12345, &varRev, &celtFetched);
Tom>   
Tom>    if ((hr = S_OK) && (celtFetched))
Tom>    {
Tom>        //тут проверяй свои елементы массива,
Tom>        //только столько членов, сколько вернулось в celtFetched
Tom>    }
Tom>} while (celtFetched)
Tom>




    IUnknownPtr spUnk = spDestinationDoc->Revisions->Get_NewEnum();
    CComQIPtr<IEnumVARIANT, &IID_IEnumVARIANT> pNewEnum = spUnk;

    
    ULONG celtFetched;
    HRESULT hr;
    do 
    {
        VARIANT varRev[1024];
         for (long l=0; l<1024; l++)
              VariantInit(&varRev[l]);

        celtFetched = 0; //Обнулить на всякий случай
        hr = pNewEnum->Next(1024, varRev, &celtFetched);

        if (celtFetched)
        {
            TRACE0("\n");
            //тут проверяй свои елементы массива,
            //только столько членов, сколько вернулось в celtFetched
        }
    } while (celtFetched);


Уходит на бесконечный цикл...
Re[5]: Работа с ревизиями Word из С++
От: paharelau  
Дата: 13.01.03 16:49
Оценка:
Здравствуйте, paharelau, Вы писали:

P>Здравствуйте, Tom, Вы писали:


P>>>Можно пример кода?


Tom>>Примерно так, но я ессно не компилировал

Tom>>
Tom>>VARIANT varRev[12345];
Tom>>ULONG celtFetched;
Tom>>HRESULT hr;

Tom>>//Тут проинициализировать весь массив вариантов
Tom>>do 
Tom>>{
Tom>>    celtFetched = 0; //Обнулить на всякий случай
Tom>>    hr = pNewEnum->Next(12345, &varRev, &celtFetched);
Tom>>   
Tom>>    if ((hr = S_OK) && (celtFetched))
Tom>>    {
Tom>>        //тут проверяй свои елементы массива,
Tom>>        //только столько членов, сколько вернулось в celtFetched
Tom>>    }
Tom>>} while (celtFetched)
Tom>>


P>


P>
P>    IUnknownPtr spUnk = spDestinationDoc->Revisions->Get_NewEnum();
P>    CComQIPtr<IEnumVARIANT, &IID_IEnumVARIANT> pNewEnum = spUnk;

P>    
P>    ULONG celtFetched;
P>    HRESULT hr;
P>    do 
P>    {
P>        VARIANT varRev[1024];
P>         for (long l=0; l<1024; l++)
P>              VariantInit(&varRev[l]);

P>        celtFetched = 0; //Обнулить на всякий случай
P>        hr = pNewEnum->Next(1024, varRev, &celtFetched);

P>        if (celtFetched)
P>        {
P>            TRACE0("\n");
P>            //тут проверяй свои елементы массива,
P>            //только столько членов, сколько вернулось в celtFetched
P>        }
P>    } while (celtFetched);
P>


P> Уходит на бесконечный цикл...


Забыл сказать. Это происходит в случае абсолютно различных документов на Word XP. Если документы призошли один от другого — все работает корректно, т.е. то что и было
Re[6]: Работа с ревизиями Word из С++
От: Tom Россия http://www.RSDN.ru
Дата: 13.01.03 18:26
Оценка:
Скорее всего он просто возвращает пустые варианты. Вставь ещё проверку на то, что варианты не пустые.
      IUnknownPtr spUnk = spDestinationDoc->Revisions->Get_NewEnum();
      CComQIPtr<IEnumVARIANT, &IID_IEnumVARIANT> pNewEnum = spUnk;
      pNewEnum->Reset();

   
      ULONG celtFetched;
      HRESULT hr;
      bool bArrayEmpty;
      VARIANT varRev[1024];
      do 
      {
         /*
          Инициализация
         */ 
         for (long l=0; l<1024; l++)
               VariantInit(&varRev[l]);

          celtFetched = 0;
          bArrayEmpty = true;

          /*
           Получаем коллекцию
          */
          hr = pNewEnum->Next(1024, varRev, &celtFetched);

          /*
           Проверяем результат
          */
          if (celtFetched)
          {
              /*
               Проходимся по всем вариантам, которые нам вернули,
               и если хотя бы один из них не пустой, то делаем чё надо
              */
              for (long l=0; l<celtFetched; l++)
                  if varRev[l].vt <> VT_EMPTY
                  {
                      bArrayEmpty = false;
                      //Делаем полезную работу здесь
                      break;
                  }
          }
} while ((celtFetched) && (!bArrayEmpty));
Народная мудрось
всем все никому ничего(с).
Re[7]: Работа с ревизиями Word из С++
От: paharelau  
Дата: 14.01.03 12:34
Оценка:
Здравствуйте, Tom, Вы писали:

Tom>Скорее всего он просто возвращает пустые варианты. Вставь ещё проверку на то, что варианты не пустые.

Tom>
Tom>      IUnknownPtr spUnk = spDestinationDoc->Revisions->Get_NewEnum();
Tom>      CComQIPtr<IEnumVARIANT, &IID_IEnumVARIANT> pNewEnum = spUnk;
Tom>      pNewEnum->Reset();

Tom>   
Tom>      ULONG celtFetched;
Tom>      HRESULT hr;
Tom>      bool bArrayEmpty;
Tom>      VARIANT varRev[1024];
Tom>      do 
Tom>      {
Tom>         /*
Tom>          Инициализация
Tom>         */ 
Tom>         for (long l=0; l<1024; l++)
Tom>               VariantInit(&varRev[l]);

Tom>          celtFetched = 0;
Tom>          bArrayEmpty = true;

Tom>          /*
Tom>           Получаем коллекцию
Tom>          */
Tom>          hr = pNewEnum->Next(1024, varRev, &celtFetched);

Tom>          /*
Tom>           Проверяем результат
Tom>          */
Tom>          if (celtFetched)
Tom>          {
Tom>              /*
Tom>               Проходимся по всем вариантам, которые нам вернули,
Tom>               и если хотя бы один из них не пустой, то делаем чё надо
Tom>              */
Tom>              for (long l=0; l<celtFetched; l++)
Tom>                  if varRev[l].vt <> VT_EMPTY
Tom>                  {
Tom>                      bArrayEmpty = false;
Tom>                      //Делаем полезную работу здесь
Tom>                      break;
Tom>                  }
Tom>          }
Tom>} while ((celtFetched) && (!bArrayEmpty));
Tom>




Все одно в бесконечный цикл входит.

Вот пример рабочего кода(Word 2000&XP)

Word::_AplicationPtr spWord;

...

spDestinationDoc->Range(&_variant_t(0L), &_variant_t(0L))->Select();
Word::SelectionPtr pSel = spWord->GetSelection();

long count = spDestinationDoc->Revisions->Count;
Word::RevisionPtr spRevision = pSel->NextRevision();
do
{
 try{

    //делаем что-то
  
    spDestinationDoc->Range(&_variant_t(spRevision->Range->End), 
                            &_variant_t(spRevision->Range->End))->Select();
    pSel = spWord->GetSelection();
   }
 catch(...)
  {
    ...
  }

  spRevision = pSel->NextRevision();
  count--;
  spDestinationDoc->UndoClear();

}while(spRevision!=NULL && count);


Только работает медленнее. Может есть идея как ускорить?
Re[8]: Работа с ревизиями Word из С++
От: Tom Россия http://www.RSDN.ru
Дата: 14.01.03 12:57
Оценка: 2 (1)
P>Все одно в бесконечный цикл входит.
Может это баг ?

P>Вот пример рабочего кода(Word 2000&XP)


P>
P>Word::_AplicationPtr spWord;

P>...

spDestinationDoc->>Range(&_variant_t(0L), &_variant_t(0L))->Select();
P>Word::SelectionPtr pSel = spWord->GetSelection();

P>long count = spDestinationDoc->Revisions->Count;
P>Word::RevisionPtr spRevision = pSel->NextRevision();
P>do
P>{
P> try{

P>    //делаем что-то
P>  
P>    spDestinationDoc->Range(&_variant_t(spRevision->Range->End), 
P>                            &_variant_t(spRevision->Range->End))->Select();
P>    pSel = spWord->GetSelection();
P>   }
P> catch(...)
P>  {
P>    ...
P>  }

P>  spRevision = pSel->NextRevision();
P>  count--;
P>  spDestinationDoc->UndoClear();

P>}while(spRevision!=NULL && count);
P>


P>Только работает медленнее. Может есть идея как ускорить?

В Next получай сразу все значения. Т.е
pVar = new VARIANT[spDestinationDoc->Revisions->Count] и затем это в Next... В общем как это делать я уже писал выше
Народная мудрось
всем все никому ничего(с).
Re[8]: Ревизии и рекурсивность
От: Vi2 Удмуртия http://www.adem.ru
Дата: 14.01.03 13:45
Оценка:
Здравствуйте, paharelau, Вы писали:

P>Все одно в бесконечный цикл входит.

А может у тебя количества Ревизий увеличиваются (или изменяется) после каждого действия с документами? Сам я с этим не работал, сразу извиняюсь за возможную глупость. Но это очень похоже на реализацию реакции на изменение чего-то, в которой это что-то изменяется.

Если это так, то правильно советует Tom — считай все ревизии и все характеристики этих ревизий у одного документа, потом у другого и затем сравнивай или делай то, что нужно.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[9]: Работа с ревизиями Word из С++
От: paharelau  
Дата: 14.01.03 14:57
Оценка:
Здравствуйте, Tom, Вы писали:

P>>Все одно в бесконечный цикл входит.

Tom>Может это баг ?

P>>Вот пример рабочего кода(Word 2000&XP)


P>>
P>>Word::_AplicationPtr spWord;

P>>...

spDestinationDoc->>>Range(&_variant_t(0L), &_variant_t(0L))->Select();
P>>Word::SelectionPtr pSel = spWord->GetSelection();

P>>long count = spDestinationDoc->Revisions->Count;
P>>Word::RevisionPtr spRevision = pSel->NextRevision();
P>>do
P>>{
P>> try{

P>>    //делаем что-то
P>>  
P>>    spDestinationDoc->Range(&_variant_t(spRevision->Range->End), 
P>>                            &_variant_t(spRevision->Range->End))->Select();
P>>    pSel = spWord->GetSelection();
P>>   }
P>> catch(...)
P>>  {
P>>    ...
P>>  }

P>>  spRevision = pSel->NextRevision();
P>>  count--;
P>>  spDestinationDoc->UndoClear();

P>>}while(spRevision!=NULL && count);
P>>


P>>Только работает медленнее. Может есть идея как ускорить?

Tom>В Next получай сразу все значения. Т.е
Tom>pVar = new VARIANT[spDestinationDoc->Revisions->Count] и затем это в Next... В общем как это делать я уже писал выше


Все это работает только в случае если документ — это измененный базовый. Иначе мы получаем массив, но не тот! Все ревизии имеют тип Word::wdNoRevision.
Re[10]: Работа с ревизиями Word из С++
От: Tom Россия http://www.RSDN.ru
Дата: 14.01.03 16:10
Оценка:
P>Все это работает только в случае если документ — это измененный базовый. Иначе мы получаем массив, но не тот! Все ревизии имеют тип Word::wdNoRevision.
Так вроде так и должно быть. Revisions Collection — это же коллекция изменений.

A collection of Revision objects that represent the changes marked with revision marks in a range or document.


Или я чего то не понимаю ?
Народная мудрось
всем все никому ничего(с).
Re: Tomу
От: paharelau  
Дата: 16.01.03 14:06
Оценка:
Если можешь, свяжись со мной по ICQ 121699615. Я просто загибаюсь с этими коллекциями
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.