Drawings SDK Developer Guide > Working with .dwg Files > Working with Databases > Working with Database Containers > Working with Predefined Tables of Named Records > Basics of Predefined Tables of Named Records > Iterating through Records
Iterating through Records

The OdDbSymbolTableIterator class is a ready-to-use class that provides the base interface for bidirectional iterators that are hard-associated with collections of objects that are organized as predefined tables of named records in the database. The iterator performs traversing through records of a table while taking into account the erase status of the records and the direction of movement. The iterator can be used multiple times for traversing through records from the beginning to the endor from the end to the beginning of the predefined table. Working with iterators includes the following operations: creating an iterator, setting an iterator to the beginning or end of the table, moving an iterator to the next or previous record in the table, checking whether the traversing is completed, searching a record, and getting a record from the table.

The OdDbSymbolTableIteratorPtr class is the smart pointer to the iterator of any predefined table of named records. This class is used as a pointer for storing and passing references to the iterators for the following objects: blocks, layers, linetypes, dimension styles, text styles, user coordinate systems, registered applications, views, and viewports. The OdDbSymbolTableIterator class is derived from the OdRxObject class and inherits its interface. In the following examples, the pTable variable stores a pointer to the predefined table object.

Creating an iterator

The iterator must be created before traversing. To create a new iterator, declare a variable of the OdDbSymbolTableIteratorPtr type and call the newIterator() method of the predefined table object which creates the instance of the new iterator and sets it to the start record object in the predefined table. The newIterator() method has two optional arguments — the start position set as a Boolean value (true – first record or false – last record) and the erase status as a Boolean value (true – only unerased records or false – records of any status) — and returns the smart pointer to the created iterator. Both arguments are True by default. For example:


// Create a new iterator and set it on of the first unerased record
OdDbSymbolTableIteratorPtr itRecord = pTable->newIterator();
OdDbSymbolTableIteratorPtr itRecord1 = pTable->newIterator(true, true);

// Create a new iterator and set it on of the last unerased record
OdDbSymbolTableIteratorPtr itRecord2 = pTable->newIterator(false, true);

// Create a new iterator and set it on the first erased or unerased record
OdDbSymbolTableIteratorPtr itRecord3 = pTable->newIterator(true, false);

// Create a new iterator and set it on the last erased or unerased record
OdDbSymbolTableIteratorPtr itRecord4 = pTable->newIterator(last, false);

Shifting an iterator to the start position

To set the start position of the iterator to the first or last record, use the start() method that has two optional arguments — the start position to be set as a Boolean value (true – first record or false – last record) and erase status as a Boolean value (true – only unerased record or false – record of any status) — and sets the iterator on the specified position in the predefined table. Both arguments are a True by default. For example:


itRecord->start();                  // move to the first unerased record
itRecord1->start(true, true);       // move to the first unerased record
itRecord2->start(false, true);      // move to the last unerased record
itRecord3->start(true, false);      // move to the first erased or unerased record
itRecord4->start(false, false);     // move to the last erased or unerased record

Moving an iterator

To move the iterator to the next or previous record, use the step() method that has two optional arguments — the direction to be moved as a Boolean value (true – next record or false – previous record) and the erase status as a Boolean value (true – erased records are skipped or false – all records of any status) — and traverses the iterator in the specified direction through records of the predefined table taking into account their erase status. Both arguments are True by default. For example:


itRecord->step();                   // move to the next unerased record
itRecord1->step(true, true);        // move to the next unerased record
itRecord2->step(false, true);       // move to the previous unerased record
itRecord3->step(true, false);       // move to the next erased or unerased record
itRecord4->step(false, false);      // move to the previous erased or unerased record

Checking an iterator

To check whether the traversing is complete, use the done() method which does not have arguments and returns True if the iterator is out of the traverse scope or False if the iterator is within the traverse scope. For example:


// Check the traverse status
odPrintConsoleString(L"\nTraversing \"%ls\" completed", ((itRecord->done()) ? L"is" : L"is not")));

// Standard loop for traversing
while(!itRecord->done()) itRecord->step();

Getting an object using the iterator

To get a record from the table, use the getRecord() and getRecordId() methods, which differ by the returned value.

The getRecord() method has two optional arguments — the mode for opening the current record object as a value of the OdDb::OpenMode enumerator (kForRead, kForWrite, or kForNotify) and the erase status as a Boolean value (true – open the erased record or false – open the unerased record) — and returns the smart pointer to the record object to which the iterator refers. The returned value has the OdDbSymbolTableRecordPtr type, but it can be cast to the specific record type. The first argument is OdDb::kForRead by default; the second argument is False by default. For example:


// Open the unerased record in the read-only mode
OdDbSymbolTableRecordPtr pRecord = itRecord->getRecord();
OdDbSymbolTableRecordPtr pRecord1 = itRecord1->getRecord(OdDb::kForRead, false);

// Open the unerased record in the write mode
OdDbSymbolTableRecordPtr pRecord2 = itRecord2->getRecord(OdDb::kForWrite, false);

// Open the erased record in the notify mode
OdDbSymbolTableRecordPtr pRecord3 = itRecord3->getRecord(OdDb::kForNotify, true);

// Open the erased record in the write mode
OdDbSymbolTableRecordPtr pRecord4 = itRecord4->getRecord(OdDb::kForWrite, true);

The getRecordId() method does not have arguments and returns the OdDbObjectId instance associated with the record object to which the iterator refers. For example:


// Get the unerased record object
OdDbObjectId idObj1 = itRecord1->getRecordId();

// Get the erased record object
OdDbObjectId idObj3 = itRecord3->getRecordId();

To get the smart pointer to the instance of the obtained record object, use the safeOpenObject() method of the OdDbObjectId object which opens the object associated with the specified ID in the specified open mode for the specified erase status, and returns the smart pointer to the opened object of the OdDbObjectPtr type. For example:


// Open the unerased object in the read mode
OdDbObjectPtr pObj1 = idObj1.safeOpenObject(OdDb::kForRead, false);

// Open the unerased or erased object in the write mode
OdDbObjectPtr pObj3 = idObj3.safeOpenObject(OdDb::kForWrite, true);

Searching for a record using the iterator

To search for a record in the table, use the seek() method which sets the iterator to the position of the found record object that satisfied the conditions and has two implementations. Both implementations exclude erased record objects.

The first implementation of the seek() method requires one argument — the Object ID of the record object to be found — and does not return a value. For example:


itRecord->seek(idRecord);

The first implementation of the seek() method requires one argument — the raw pointer to the record object to be found — and does not return a value. For example:


itRecord->seek(pRecord);

Deleting an iterator

To delete an existing iterator, set NULL for the smart pointer to it. For example:


itRecord = NULL;

Examples of iterating

The following example demonstrates iterating through unerased records from the beginning to the end of the predefined table for listing:


odPrintConsoleString(L"\nThe list of objects:");

for(itRecord = pTable->newIterator() ; !itRecord->done() ; itRecord->step())
  odPrintConsoleString(L"\n%s-\"%s\"-%s", itRecord->objectId().getHandle().ascii(), itRecord->getRecord()->getName().c_str());
itDict = NULL;

The following example demonstrates iterating through unerased and erased records from the end to the beginning of the predefined table:


odPrintConsoleString(L"\nThe list of linetypes:");

for(itRecord->start(false, true) ; !itRecord->done() ; itRecord->step(false, true))
{
  pRecord = itRecord->getRecord(OdDb::kForWrite, true);
  odPrintConsoleString(L"\n%s-\"%s\"-(%s)-%s", pRecord->handle().ascii(), pRecord->getName().c_str(), 
                       pRecord->isA()->name().c_str(), ((pRecord->isErased()) ? L"erased" : L"unerased"));
}

See Also

Working with Predefined Tables of Named Records

Concept of Iterators

Getting and Checking Records

Adding, Naming, Deleting, and Recovering Records

Example of Using the Record-Table Interface for Selecting Objects

Copyright © 2002 – 2021. Open Design Alliance. All rights reserved.