Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/18: Рейтинг темы: голосов - 18, средняя оценка - 4.50
0 / 0 / 0
Регистрация: 11.03.2014
Сообщений: 22

Извлечение метаданных из MS Office документов

11.03.2014, 13:25. Показов 3550. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день!

Потребовалось извлечь информацию о датах создания, изменения, последнего вывода на печать и авторе документов MS Office. В свойствах файла эта информация хранится во вкладке "Подробно". При этом даты создания и изменения во вкладке "Подробно" могут и отличаться от аналогичных во вкладке "Общие". Так как же мне средствами c++ builder 6 получить информацию из вкладки "Подробно"?

гуглила несколько дней, даже в какую сторону копать никаких намеков не нашла....
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
11.03.2014, 13:25
Ответы с готовыми решениями:

Очистка метаданных в файлах Microsoft Office
Уважаемые форумчане, возникла задача очистить личную информацию в файлах office, нашел пару программ, но работали они не идеально, основной...

Добавление и извлечение документов (Word, Excel) из БД MS Access
Доброго времени суток. Есть задача хранить и извлекать документы из БД. Потом, возможно заказчик захочет модифицировать и заливать...

Добавление и извлечение документов (Word, Excel) из БД на MS Access
Доброго времени суток. Есть задача хранить и извлекать документы из БД. Надо именно хранение в БД, по другому никак. Программа...

8
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33379 / 21503 / 8236
Регистрация: 22.10.2011
Сообщений: 36,899
Записей в блоге: 12
11.03.2014, 14:29
Office-овские файлы - это так называемые compound files, из них можно вытащить информацию при помощи COM. Работа с интерфейсами IPropertyStorage, IPropertySetStorage, ... и с функцией StgOpenStorageEx

На Дельфи где-то валялся исходник, если надо - попробую поискать...
0
0 / 0 / 0
Регистрация: 11.03.2014
Сообщений: 22
12.03.2014, 11:13  [ТС]
UI, спасибо за подсказку! Буду очень благодарна за код на Дельфи

ну и если вдруг у кого есть готовые наметки или примеры на с++, также буду очень признательна
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33379 / 21503 / 8236
Регистрация: 22.10.2011
Сообщений: 36,899
Записей в блоге: 12
12.03.2014, 11:47
Лучший ответ Сообщение было отмечено LaVie как решение

Решение

XE2:
Delphi
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
unit Unit1;
 
interface
 
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Vcl.StdCtrls;
 
type
  TForm1 = class(TForm)
    btnGo: TButton;
    LV: TListView;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
uses ActiveX, ComObj;
 
{$R *.dfm}
function StgOpenStorageEx(const pwcsName: POleStr; grfMode: LongInt;
  stgfmt: DWORD; grfAttrs: DWORD; pStgOptions: Pointer; reserved2: Pointer;
  riid: PGUID; out stgOpen: IStorage): HResult; stdcall; external 'ole32.dll';
 
const
  // GUID для набора св-в SummaryInformation
  FMTID_SummaryInformation: TGUID = '{F29F85E0-4FF9-1068-AB91-08002B27B3D9}';
  IID_IPropertySetStorage: TGUID = '{0000013A-0000-0000-C000-000000000046}';
 
  STGFMT_FILE = 3;
  STGFMT_ANY = 4;
 
type
  PPropSpecArray = ^TPropSpecArray; // массив спецификаций свойств
  TPropSpecArray = array [0 .. 999] of TPropSpec;
 
  PPropVariantArray = ^TPropVariantArray;
  // массив - приемник, куда будут помещены значения нужных свойств
  TPropVariantArray = array [0 .. 999] of TPropVariant;
 
function IsNTFS(AFileName: string): boolean;
var
  fso, drv: OleVariant;
begin
  fso := CreateOleObject('Scripting.FileSystemObject');
  drv := fso.GetDrive(fso.GetDriveName(AFileName));
  Result := drv.FileSystem = 'NTFS'
end;
 
procedure TForm1.btnGoClick(Sender: TObject);
var
  fn: string;
  stgRoot: IStorage;
  stgPS: IPropertySetStorage;
  stgP: IPropertyStorage;
  ps: PPropSpecArray;
  pv: PPropVariantArray;
 
  LVI: TListItem;
begin
  fn := 'D:\test\01.doc';
 
  // Проверяем: если это не compound file и система - не NTFS, тогда выходим.
  // (для compound файлов FS не важна)
  if (StgIsStorageFile(StringToOleStr(fn)) <> S_OK) then
    if (not IsNTFS(fn)) then
    begin
      MessageBox(Handle, 'NTFS needed for non-compound files', 'Error',
        MB_ICONERROR);
      exit;
    end;
 
 
 
  if (StgOpenStorageEx(StringToOleStr(fn), STGM_READ or STGM_SHARE_DENY_WRITE,
    STGFMT_ANY, 0, nil, nil, @IID_IPropertySetStorage, stgRoot) <> S_OK) then
  // открываем его
  begin
    MessageBox(Handle, 'Невозможно открыть файл', 'Error', MB_ICONERROR);
    exit;
  end;
 
  stgPS := stgRoot as IPropertySetStorage; // ссылаемся на нужный интерфейс
  // открываем набор свойств
  if (stgPS.Open(FMTID_SummaryInformation, STGM_READ or STGM_SHARE_EXCLUSIVE, stgP) <> S_OK) then
  begin
    MessageBox(Handle, 'Невозможно открыть набор свойств', 'Error', MB_ICONERROR);
    exit;
  end;
 
  ps := nil;
  pv := nil;
  try
    GetMem(ps, SizeOf(TPropSpec));
    GetMem(pv, SizeOf(TPropVariant));
 
    ps[0].ulKind := PRSPEC_PROPID;
 
    ps[0].propid := PIDSI_TITLE; // заголовок
    LVI := LV.Items.Add;
    LVI.Caption := 'Title';
    if (stgP.ReadMultiple(1, @ps[0], @pv[0]) = S_OK) then
      LVI.SubItems.Add(pv[0].pszVal)
    else
      // Свойство не прочиталось
      LVI.SubItems.Add('');
 
  finally
    if assigned(ps) then
      FreeMem(ps);
    if assigned(pv) then
      FreeMem(pv);
 
    stgP := nil;
    stgPS := nil;
    stgRoot := nil;
  end;
end;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  LV.Clear;
end;
 
end.
, на форме, как видишь только кнопка и ListView. Показано, как читается свойство Title с закладки Details:



Вместо PIDSI_TITLE могут использоваться вот эти идентификаторы


P.S. Вот то же самое на Билдере:
C++
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
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    String fn = L"D:\\test\\01.doc";
 
    // Проверяем: если это не compound file - тогда выходим.
    if (::StgIsStorageFile(StringToOleStr(fn)) != S_OK)
    {
        ::MessageBox(this->Handle, L"Non-Compound File", L"Error",
        MB_ICONERROR);
        return;
    }
 
    IPropertySetStorage *stgPS;
    if (::StgOpenStorageEx(StringToOleStr(fn),
        STGM_READ | STGM_SHARE_DENY_WRITE, STGFMT_ANY, 0, NULL, NULL,
        IID_IPropertySetStorage, (void**)&stgPS) != S_OK)
    {
        ::MessageBox(this->Handle, L"Невозможно открыть файл", L"Error",
            MB_ICONERROR);
        return;
    }
 
    IPropertyStorage *stgP;
    // открываем набор свойств
    if (stgPS->Open(FMTID_SummaryInformation, STGM_READ | STGM_SHARE_EXCLUSIVE,
        &stgP) != S_OK)
    {
        ::MessageBox(this->Handle, L"Невозможно открыть набор свойств",
            L"Error", MB_ICONERROR);
        return;
    }
 
    PROPSPEC ps[5];
    PROPVARIANT pv[5];
 
    ps[0].ulKind = PRSPEC_PROPID;
 
    ps[0].propid = PIDSI_TITLE; // заголовок
    TListItem *LVI = LV->Items->Add();
    LVI->Caption = "Title";
 
    if (stgP->ReadMultiple(1, &ps[0], &pv[0]) == S_OK)
        LVI->SubItems->Add(pv[0].pszVal);
    else // Свойство не прочиталось
        LVI->SubItems->Add("");
 
    stgP->Release();
    stgPS->Release();
}
Проверку на NTFS делать не стал, у тебя все равно compound-файлы. Для старых Билдеров нужно будет убрать L перед строковыми константами или использовать MessageBoxW...
3
0 / 0 / 0
Регистрация: 11.03.2014
Сообщений: 22
17.03.2014, 11:12  [ТС]
UI, спасибо ОГРОМНОЕ!!!!
0
0 / 0 / 0
Регистрация: 11.03.2014
Сообщений: 22
19.03.2014, 12:36  [ТС]
код, предложенный уважаемым UI отлично работает для doc файлов.

А как извлекать информацию из docx-файлов? (они ж, я так понимаю, не compound-файлы)
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33379 / 21503 / 8236
Регистрация: 22.10.2011
Сообщений: 36,899
Записей в блоге: 12
19.03.2014, 12:54
Цитата Сообщение от LaVie Посмотреть сообщение
они ж, я так понимаю, не compound-файлы
Угу, не compound... Зато OpenXML, так что обычный парсинг XML-файла
1
0 / 0 / 0
Регистрация: 11.03.2014
Сообщений: 22
27.03.2014, 13:30  [ТС]
что-то не могу я подцепиться к docx файлу... чтобы парсить его как xml-файл надо сперва извлечь из него это xml-файлы (docx, как я поняла, это архив, содержащий xml-файлы)? или надо как-то напрямую путь указать? или что? нагуглить ничего не получается, все примеры на С#...

обычно с xml-файлами я работаю через TXMLDocument, но тут видимо надо не так, потому что выскакивает ошибка (raised exception class EDOMParseError with message 'An invalid character was found in text content') на

C++
1
TXMLDocument *XMLDocMeta = new TXMLDocument("D:\\123.docx");
Буду особенно признательна за кусочек кода на Билдере, от которого можно дальше копать...
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
 Аватар для volvo
33379 / 21503 / 8236
Регистрация: 22.10.2011
Сообщений: 36,899
Записей в блоге: 12
27.03.2014, 15:17
docx - упакованный контейнер. Распакуй его для начала (тем же zip-ом или 7z), и посмотри, что он содержит. У меня, к счастью, нет MS Office новой версии, только OpenOffice, поэтому здесь ничем помочь не смогу, мой Word файлы docx не сохраняет (экспериментировать, соответственно, не с чем), а у OO формат немного другой.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
27.03.2014, 15:17
Помогаю со студенческими работами здесь

Отображение документов MS office
Доброго времени суток. При разработке приложения столкнулся с проблемой (ну как проблемой - без понятия вообще как) отображения...

Блокировка документов mc office word,excel
Здравствуйте, помогите пожалуйста умные люди) столкнулась с такой проблемой( не могу открыть документы в формате word,excel ,система выдает...

MS Office Word: Версии документов с исправлениями и дублирующаяся информация
Здравствуйте. Никак не могу найти в интернете ответов на свои вопросы, а хочется более эффективно организовать свою работу. Может, кто...

Обработка ошибок при открытии документов Microsoft Office
Set Document = Excel.Workbooks.Open(fileName) если документ не откроется - как обработать ошибку?

Конвертация MS Office документов (doc, xls) в графические файлы
Всем привет! Может кто сталкивался, можно ли сделать конвертацию MS Office документов (doc, xls...) в графические файлы, например, в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! в-строка - входное арифметическое выражение в инфиксной(обычной). . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru