HOWTO: Determine If an Excel Workbook Contains Macros
ID: Q224518
|
The information in this article applies to:
-
Microsoft Office 2000 Developer
-
Microsoft Excel 97 for Windows
-
Microsoft Excel for Windows 95, version 7.0
-
Microsoft Excel for Windows, version 5.0
-
Microsoft Excel 2000
SUMMARY
Microsoft Excel workbooks are OLE-structured storage files. You can detect the presence of macros by doing the following:
- Run a test to see if a substorage named _VBA_PROJECT_CUR or _VBA_PROJECT exists.
- Run a test to see if there are any 4.0 (XLM) macro sheets by searching the workbook data stream.
MORE INFORMATION
The following Microsoft Visual C++ function demonstrates how
to do this:
// Returns TRUE if Excel file contains macros.
BOOL ExcelFileContainsMacros(char *pszFilename) {
// Translate filename to UNICODE.
WCHAR wcFilename[1024];
int i = mbstowcs(wcFilename, pszFilename, strlen(pszFilename));
wcFilename[i] = 0;
// Open workbook using structured storage.
IStorage *pStg;
HRESULT hr = StgOpenStorage(wcFilename, 0,
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, 0, &pStg);
if(FAILED(hr)) return FALSE;
// Test presence of _VBA_PROJECT_CUR substorage (XL8+).
IStorage *pSubStg;
hr = pStg->OpenStorage(L"_VBA_PROJECT_CUR", 0,
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, 0, &pSubStg);
if(!FAILED(hr)) {
// VBA substorage exists.
pSubStg->Release();
pStg->Release();
return TRUE;
}
// Test presence of _VBA_PROJECT substorage (XL7+).
hr = pStg->OpenStorage(L"_VBA_PROJECT", 0,
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, 0, &pSubStg);
if(!FAILED(hr)) {
// VBA substorage exists.
pSubStg->Release();
pStg->Release();
return TRUE;
}
// Now, begin test for Excel 4.0 macro sheets.
// Open the data stream where Microsoft Excel stores the data.
IStream *pStm;
hr = pStg->OpenStream(L"Workbook", 0,
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStm);
// If "Workbook" fails, try older "Book" name...
if(FAILED(hr)) {
hr = pStg->OpenStream(L"Book", 0,
STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStm);
if(FAILED(hr)) {
pStg->Release();
return FALSE;
}
}
// Now iterate the records in the stream,
// looking for BOUNDSHEET record.
BOOL hasXl4Macros = false;
for(;;) {
// Read id and len first.
DWORD dwRead;
short id, len;
hr = pStm->Read(&id, 2, &dwRead);
// Check exit condition (end of BIFF, or read-error).
if( (FAILED(hr)) || (dwRead != 2) || (id==0x0a)) break;
pStm->Read(&len, 2, &dwRead);
// Is this a BOUNDSHEET record?
if(id == 0x85) {
// Read other fields.
int dummy, grbit;
pStm->Read(&dummy, 4, &dwRead);
pStm->Read(&grbit, 4, &dwRead);
// Adjust length for garbage run.
len -= 8;
// Check grbit to determine if it is a macro sheet.
hasXl4Macros = (grbit & 0x100) ? true : false;
// Exit, if you found what you are looking for.
if(hasXl4Macros)
break;
}
// Clear out the rest of this record.
if(len > 32766) len = 32766;
static char garbage[32766];
pStm->Read(garbage, len, &dwRead);
}
// Clean up.
pStm->Release();
pStg->Release();
return hasXl4Macros;
}
Additional query words:
macro virus
Keywords : kbExcel kbVC kbSDKExcel kbGrpDSO kbOffice2000 kbexcel2000
Version : :; WINDOWS:2000,5.0,7.0,97
Platform : WINDOWS
Issue type : kbhowto