powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / Excel 2007 - Конфликт имен
5 сообщений из 30, страница 2 из 2
Excel 2007 - Конфликт имен
    #39402699
Фотография JayDi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
big-duke,

Да, это не помогает. Что на ПК с 2007, что на ПК с 2016 офисом.

Вот пример проблемного xlsx-файла, при открытии которого из ole automation будет появляться левое окно:
https://yadi.sk/d/UHuuU9At3DrpGg

Вызов экселя:
Код: pascal
1.
2.
3.
excel := CreateOleObject('Excel.Application');
excel.DisplayAlerts  := False;
workBook := excel.WorkBooks.Add(edit_File.Text);



В workbook.xml из эксель-файла это строчки вида:
Код: xml
1.
<definedName name="Print_Area" localSheetId="4">'paaaages111'!$A$2:$J$32</definedName>



А вот так выглядит это окно:
...
Рейтинг: 0 / 0
Excel 2007 - Конфликт имен
    #39402702
Фотография JayDi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Причем проблемный файл сохранен в том же самом 2016 офисе (т.е. ошибки в именах он оставляет и никак о них не сообщает ни при сохранении, ни при открытии). Только excel automation эти ошибки замечает, чем и вызывает большие проблемы -- процесс открытия файла "зависает" до тех пор, пока пользователь не введет новое имя в этом окне (самих окошек может быть несколько).
...
Рейтинг: 0 / 0
Excel 2007 - Конфликт имен
    #39416944
Фотография JayDi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так и не нашел решений средствами экселя. Поэтому сделал через патч, как советовали выше. Вот пример кода (с некоторым мусор, но тем ни менее, может пригодится кому -- не забываем потом временные файлы удалять). Разница в том, что тут используются стандартные компоненты для делфи (а не зим-мастер как выше):

код распакови во временный файл, изменения и запаковки обратно
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
procedure PrepareSourceFileName(const ANewFile: string);
const
  WORKBOOK_FILE = 'xl\workbook.xml';
var
  tempFile: string;
  tempDir: string;
  tempXml: string;
  fileIndex: Integer;
  zip: TZipFile;
  XMLDoc, aNode, aNodeList: Variant;
  I: Integer;

  function GetFileIndex(AZip: TZipFile): Integer;
  var
    I: Integer;
  begin
    Result := -1;
    for I := 0 to AZip.FileCount - 1 do
    begin
      if ReplaceStr(AZip.FileNames[I], '/', '\') = WORKBOOK_FILE then
      begin
        Result := I;
        Break;
      end;
    end;
  end;

begin
  // фикс для старых эксель-файлов, где могут быть проблемы с именами в области печати (Print_Area)
  // Агафонов Олег, jaydi85@gmail.com
  // пример решения см. на http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=543092&msg=15183800

  // если что-то не так, то будет открываться оригинальный файл
  Self.FSourceFile := ANewFile;
  Self.IsClearTempFile := False;

  zip := TZipFile.Create;
  XMLDoc := Null;
  Screen.Cursor := crHourGlass;
  try
    try
      zip.Open(FSourceFile, TZipMode.zmRead);
    except
      Exit;
    end;
    fileIndex := GetFileIndex(zip);
    if fileIndex < 0 then
    begin
      Exit;
    end;

    // пересоздаем во временный файл
    FreeAndNil(zip);
    tempFile := TPath.GetTempFileName;
    TFile.Copy(FSourceFile, tempFile, True);
    Assert(FileExists(tempFile));

    tempDir := ExtractFileDir(tempFile) + '\' + ReplaceStr(ExtractFileName(tempFile), ExtractFileExt(tempFile), '');
    ForceDirectories(tempDir);

    // распаковываем файлы в xml
    TZipFile.ExtractZipFile(tempFile, tempDir);
    tempXml := tempDir + '\' + WORKBOOK_FILE;
    Assert(FileExists(tempXml));

    // заменяем проблемную строчку
    XMLDoc := CreateOleObject('MSXML2.DOMDocument');
    XMLDoc.async := False;
    XMLDoc.load(tempXml);
    XMLDoc.setProperty('SelectionLanguage', 'XPath');
    XMLDoc.SetProperty('SelectionNamespaces', 'xmlns:wrk="http://schemas.openxmlformats.org/spreadsheetml/2006/main"');

    if not (XMLDoc.parseError.reason = '') then
    begin
      ShowMessage('Не удалось преобразовать файл по причине:' + sLineBreak + sLineBreak + XMLDoc.parseError.reason);
      Exit;
    end;

    // автозамена на другое имя
    //aNodeList := XMLDoc.selectNodes('//wrk:definedName[@name=''_xlnm._FilterDatabase'']');
    aNodeList := XMLDoc.selectNodes('//wrk:definedName[@name=''_xlnm.Print_Area'']');
    for I := 0 to aNodeList.Length - 1 do
    begin
      aNode := aNodeList.item[I];
      aNode.setAttribute('name', '_xlnm.SomePrintAreaFix');
    end;
    XMLDoc.save(tempXml);

    // файл готов, пакуем обратно
    TZipFile.ZipDirectoryContents(tempFile, tempDir);
    Assert(FileExists(tempXml));

    // подчищаем
    TDirectory.Delete(tempDir, True);

    // ВСЕ ОК
    Self.FSourceFile := tempFile;
    Self.IsClearTempFile := True;
  finally
    FreeAndNil(zip);
    XMLDoc := Null;
    Screen.Cursor := crDefault;
  end;
end;

...
Рейтинг: 0 / 0
Excel 2007 - Конфликт имен
    #39434203
Мария19
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Просто введите такое же новое имя, только добавьте в новом в конце, например 1.
...
Рейтинг: 0 / 0
Excel 2007 - Конфликт имен
    #39442344
ROLpogo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Trikon, спасибо, помогло!

Вот вариант под C++Builder:

*.h
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
class TResolveNameConflict : public TThread
{
private:
  bool *m_pbClose;
protected:
  void __fastcall Execute();
public:
  __fastcall TResolveNameConflict(bool CreateSuspended);
  void __fastcall SetClose(bool* pbClose);
};


*.cpp
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
/// Поток для схлопывания окна с ошибкой ///////////////////////////////////////
__fastcall TResolveNameConflict::TResolveNameConflict(bool CreateSuspended) : TThread(CreateSuspended)
{
  m_pbClose = false;
}
//---------------------------------------------------------------------------
void __fastcall TResolveNameConflict::SetClose(bool *pbClose)
{
  m_pbClose = pbClose;
}
//---------------------------------------------------------------------------
void __fastcall TResolveNameConflict::Execute()
{
  FreeOnTerminate = true;
  HWND wnd,
       wnd_child;

  while (!*m_pbClose)
  {
    wnd = FindWindow(NULL, "Конфликт имен");

    if (wnd != 0)
    {
      wnd_child = ChildWindowFromPoint(wnd, Point(100, 55));
      SendMessage(wnd_child, WM_SETFOCUS, 0, 0);
      SendMessage(wnd_child, EM_SETSEL, 100, 55);
      SendMessage(wnd_child, WM_CHAR, char('A'), 0);
      wnd_child = ChildWindowFromPoint(wnd, Point(200, 90));
      SendMessage(wnd_child, EM_SETSEL, 200, 90);
      SendMessage(wnd, WM_KEYDOWN, VK_RETURN, 1);
      SendMessage(wnd, WM_KEYUP,   VK_RETURN, 1);
    }
    Sleep(500);
  }
  Terminate();
}



Вызов в коде открытия Excel файла:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
  bool bCloseThread = false;
  try
  { //Попытка открытия
    if (!m_XL_Books.IsNull())
    {
      m_pThreadRNC = new TResolveNameConflict(true);
      m_pThreadRNC->SetClose(&bCloseThread);
      m_pThreadRNC->Resume();

      m_XL_Books.OleProcedure("Open", WideString(sFileName).c_bstr());
      bCloseThread = true;
    }
  }
  catch(...)
  { //Попытка не удалась
    bCloseThread = true;
  }
...
Рейтинг: 0 / 0
5 сообщений из 30, страница 2 из 2
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / Excel 2007 - Конфликт имен
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]