1 (изменено: Rom5, 2012-02-25 01:08:40)

Тема: VBS: Пример получения свойств документов Офиса

Коллеги, представляю пример скрипта переименовывания документов Офиса на основании их свойств (автор, заголовок и проч.)

Предистория: после восстановления офисных файлов с зачищенного "нежданной" установкой операционки с нуля (глюк SCCM) винта программой "Restorer2000" в разделе восстановления "Lost Files" находятся восстановленые по типам данных файлы, но имена файлов - просто числовое перечисление, а даты всех файлов - это дата восстановления.

Написанный "на коленке" скрипт Rename_OfficeDoc.vbs пробует получить из вордов/экселей свойства: дату модификации, имена автора и последнего правившего документ, заголовок документа - и формирует из этого новое имя файла по шаблону:
ГГГГ-ММ-ДД_ччмм _(е)автор_последних_правок _(t)заголовок_документа _(a)автор_документа _(прежнее_имя).*
Если (a) совпадает с (e), то автора не показываем.

Этим скриптом я отсеял "битые" документы (где-то 10-20%), а на остальные - дал пользователю через переименование хоть какие-то намеки на содержимое и давность 4тыс. восстановленных документов, т.к. юзер видит документы в хронологии модификации и может понять - от кого получен, кем редактирован.

При работе скрипта используется объект "DSOFile.OleDocumentProperties" (регистрируем библиотеку dsofile.dll). Данная DLL в свободном скачивании - Microsoft Developer Support OLE File Property Reader 2.1 Sample (KB 224351) .

'--- RenamedDoc.vbs'
' Reading Document Properties, rename documents

' Путь к обрабатывемому каталогу'
' sFolder = "C:\Common\Develop\vbs\RenamedDoc\doc1"
' sFolder = "\\uachpc077\c$\!ins\_RECOVER_FROM_036\Microsoft Excel 2007 XML Document"
sFolder = "\\uachpc077\c$\!ins\_RECOVER_FROM_036\Microsoft Word 2007 XML Document"

gi_NeedTitle  = 1 ' 1 - добавляем Title документа / 0 - не обрабатываем, если остались документы с заголовком в нечитабельной кодировки'
gi_NeedRename = 1 ' 1 - переименовываем документы / 0 - только формируем протокол (в папке документов) _log_RenamedDoc.txt с новыми именами'

Set fso = CreateObject("Scripting.FileSystemObject")  
Set NewFile = fso.CreateTextFile( sFolder & "\_log_RenamedDoc.txt", True)
Set folder = fso.GetFolder(sFolder)
Set files = folder.Files
countDoc = 0 : countErr = 0 : countRen = 0
For each folderIdx In files
	If ( InStr(folderIdx.Name,".xls")>0 OR InStr(folderIdx.Name,".doc")>0 ) AND Left(folderIdx.Name, 2)<>"~$" Then
		countDoc = countDoc + 1
		sOldName = folderIdx.Name
		sLog = ""
		sNewName = uf_newNameDocFile (sFolder, sOldName)
		If sNewName=sOldName Then
			countErr = countErr + 1
			sLog = "(no_read)" & vbTab & sOldName & vbTab & "--"
		Else
			'--- переименование файла'
			Err.Clear
			On Error Resume Next
			If gi_NeedRename=1 Then fso.MoveFile sFolder &"\"& sOldName, sFolder &"\"& sNewName
			If Err.Number = 0 Then
				countRen = countRen + 1
				sLog = "(renamed)" & vbTab & sOldName & vbTab & sNewName 
			Else
				countErr = countErr + 1
				sLog = "(err_rename)" & vbTab & sOldName & vbTab & sNewName 
			End IF
			On Error GoTo 0
		End IF
		
		NewFile.WriteLine( sLog )
	End IF
	
Next
NewFile.Close

s = "Doc:" & Cstr(countDoc) & " Err:" & Cstr(countErr) & " Ren:"  & Cstr(countRen)

msgbox s,,"Finish"


' --- Формирование нового имени файла'
' Параметры: путь к документу, имя файла документа (файл должен быть word/excel)
' Резульат - новое имя файла с добавленными слевой стороны имени файла свойствами офисного документа: 
'   дата, последний_редактировавший, заголовок, автор_документа (если отличен от редактировавшего)'
' --------------------------------------------------------------------------------------------------
Function uf_newNameDocFile (pPath, pName)

	' Microsoft Developer Support OLE File Property Reader 2.1 Sample (KB 224351)
	' http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=8422
	Dim objDoc : Set objDoc = CreateObject("DSOFile.OleDocumentProperties")
	
	i = InStrRev( pName, "." )
	sOld = Left( pName, i - 1) 'только имя файла'
	ext = Right( pName, Len(pName) - i ) 'расширение файла'
	s = ""
	
	Err.Clear
	On Error Resume Next
	objDoc.Open( pPath & "\" & pName) 
	If Err.Number = 0 Then
		sDt = "" 'время последнего редактирования в формате ГГГГ-ММ-ДД_ЧЧММ'
		If len(Trim(objDoc.SummaryProperties.DateLastSaved))>0 Then 
			sDt = objDoc.SummaryProperties.DateLastSaved
			sDt = Mid(sDt,7,4) & "-" &  Mid(sDt,4,2) & "-" & Mid(sDt,1,2) & "_" & Replace(Mid(sDt,12,5),":","")
		End IF
		If len(sDt)>0 AND sDt<>"--_" Then s = s & sDt
		If len(objDoc.SummaryProperties.LastSavedBy)>0 Then s = s & " _(e)"& objDoc.SummaryProperties.LastSavedBy
		If gi_NeedTitle=1 Then 'есть требование обрабатывать Title'
			If len(objDoc.SummaryProperties.Title)>0 Then 
				sTitle = Trim( Replace(Replace(objDoc.SummaryProperties.Title, vbTab,""), "|",""))
				If sTitle="Number:" Then sTitle=""
				If Len(sTitle)>0 Then s = s & " _(t)"& sTitle
			End IF
		End IF
		If len(objDoc.SummaryProperties.Author)>0 AND (objDoc.SummaryProperties.Author<>objDoc.SummaryProperties.LastSavedBy) _
			Then s = s & " _(a)"& objDoc.SummaryProperties.Author
		' замены недопустимых и часто повторяемых символов'
		s = Replace(s,"і","i") 'украинская литера на латинскую'
		s = Replace(s,"“","`") 'разновидности кавычек'
		s = Replace(s,"”","`")
		s = Replace(s,"«","`")
		s = Replace(s,"»","`")
		s = Replace(s,"""","`")
		s = Replace(s,"?","_") 'символы подстановок'
		s = Replace(s,"*","_")
		s = Replace(s,":","_")
		s = Replace(s,"/","_")
		s = Replace(s,"\","_")
		s = Replace(s,"|","_")
		s = Replace(s,"____","__") 'многократные дубли пробелов и подчеркиваний'
		s = Replace(s,"____","__")
		s = Replace(s,"____","__")
		s = Replace(s,"  "," ")
		s = Replace(s,"  "," ")
	End IF
	If Len(s)> 0 Then s = s & " (" & sOld& ")." & ext Else s = pName 'оставляем имя прежним, если свойства не были получены'
	On Error GoTo 0
			
	Set objDoc = Nothing
	uf_newNameDocFile = s
End FUNCTION

Скрипт писался на скорую руку, поэтому нет передачи аргументов, обхода каталогов и прочего - в первых строках скрипта выполняются индивидуальные настройки. Обработка каталога с doc/docx/xls/xlsx выклядела так:
- правим путь к обрабатывемому каталогу
- запускаем скрипт, ждем сообщения "Финиш"
- переименованные файлы, выделив по маске *_*.* , перекладываем в другую папку
- анализируем в протоколе _log_RenamedDoc.txt записи "(err_rename)" - определяем, что может в Titlt мешать переименовать файл. Если в Title документа какая-то нечитабельная каша - отключаем в скрипте обработку свойства Title: gi_NeedTitle = 0
- Повторяем обработку, перенос переименованных файлов и анализ протокола. Если в логе остаются только записи "(no_read)", то оставшиеся непереименованые файлы - битые.

Пример файла протокола:

(no_read)    119880.doc    --
(err_rename)    122475.doc    2003-09-26_1045 _(e)DokuchayevaL _(t)ПЕРЕЛІК ДОКУМЕНТІВ, НЕОБХІДНИХ ДЛЯ ВІДКРИТТЯ КОРПОРАТИВНОГО РАХУНКУ В НАЦІОНАЛЬНІЙ ВАЛЮТІ ТИПУ “Н” ТА РАХУНКУ В ІНОЗЕМНІЙ ВАЛЮ _(a)Gvozdyev Yuriy (122475).doc
(renamed)    128002.doc    2009-07-03_1050 _(e)NeduzhyiS _(t)Постачальник_        ПП `МОСТ-СЕРВІС` _(a)user (128002).doc
(renamed)    128462.doc    2009-11-23_1739 _(e)NeduzhyiS _(t)Оплата за рекламу в журналi ` Партнер -Черкаси` № 10-12, 2009 р (128462).doc
(renamed)    251401.doc    2011-10-12_1812 _(e)VietrovS _(t)Оплата за марки поштовi для регiонального вiддiлення АТ ` ОТП Банк` в м _(a)NeduzhyiS (251401).doc

Может кому-то это пригодится.

WBR. Roman