Hi Comm,
I wrote this function to purge anonymous blocks. It works but only at top level: it doesn't work with nested blocks.
If I try to loop the function until the ObjectIdArray is empty, it seems to go well, but if you use AUDIT on DWG after the "purge execution" the nested blocks re-appear.
Acad::ErrorStatus Grazie::purge()
{
Acad::ErrorStatus es;
AcDbObjectIdArray ids;
AcDbObjectId id;
CString nome=L"";
AcDbObjectId tblRecId;
AcDbDatabase *pDbUse=acdbHostApplicationServices()->workingDatabase();
ids.setLogicalLength(0).setPhysicalLength(0);
AcDbBlockTable *pBlockTable;
es=acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable, AcDb::kForWrite);
AcDbBlockTableIterator* tblIter;
es = pBlockTable->newIterator(tblIter);
if (es == Acad::eOk)
{
// walk table and just collect all the objIds
// of the entries
for (; !tblIter->done(); tblIter->step())
{
AcDbBlockTableRecord* blkRec;
es = tblIter->getRecord(blkRec, AcDb::kForWrite);
if (es == Acad::eOk)
{
//if(blkRec->isKindOf(AcDbBlockReference::desc()))
{
if (blkRec->isAnonymous())
{
ACHAR* locName;
blkRec->getName(locName);
id=blkRec->id();
ids.append(id);
}
}
blkRec->close();
}
}
delete tblIter;
}
pBlockTable->close();
es=pDbUse->purge(ids);
es = pBlockTable->newIterator(tblIter);
if (es == Acad::eOk)
{
// walk table and just collect all the objIds
// of the entries
for (; !tblIter->done(); tblIter->step())
{
AcDbBlockTableRecord* blkRec;
es = tblIter->getRecord(blkRec, AcDb::kForWrite);
if (es == Acad::eOk)
{
//if(blkRec->isKindOf(AcDbBlockReference::desc()))
{
if (blkRec->isAnonymous())
{
ACHAR* locName;
blkRec->getName(locName);
id=blkRec->id();
if(ids.find(id)>=0)
{
nome=L"";
nome=locName;
// if(nome.Find(L"*D")==0 || nome.Find(L"*U")==0)
es=blkRec->erase();
}
}
}
blkRec->close();
}
}
delete tblIter;
}
pBlockTable->close();
ids.setLogicalLength(0).setPhysicalLength(0);
return es;
}
What can I do to Fix the problem?
Thank You,
Regards,
Mario
Hi,
this is very simple. Just run an loop until no purgeable ID's were found.
It is not a good idea to erase entries of the blocktable during an iterator loop. Although I'm not sure whether this causes your problem. You already have the AcDbObjectId s collected, so you can write the second part of your function like this:
int i, nCount = ids.length(); for (i = 0; i < nCount; ++i) { AcDbBlockTableRecord* blkRec=NULL; if ( (es=acdbOpenObject(blkRec, ids[i], AcDb::kForWrite)) == Acad::eOk ) { es = blkRec->erase(); blkRec->close(); } }
Besides that the second call of es = pBlockTable->newIterator(tblIter); is carried out after pBlockTable was closed!
By the way: If you use a non-const ACHAR* for
ACHAR* locName;
blkRec->getName(locName);
You have to release the memory for it with acutDelString(locName)! I recomment using const ACHAR *locName=NULL; instead. You don't have to release the memory than.