Make single part per line BOM generation compare all component fields.

This commit is contained in:
Marco Mattila 2012-02-22 23:37:34 +02:00
parent 0a68744e2d
commit 97884551f0
5 changed files with 63 additions and 135 deletions

View File

@ -42,6 +42,13 @@
//#define USE_OLD_ALGO //#define USE_OLD_ALGO
void SCH_REFERENCE_LIST::RemoveItem( int aIndex )
{
if( aIndex < componentFlatList.size() )
componentFlatList.erase( componentFlatList.begin() + aIndex );
}
bool SCH_REFERENCE_LIST::sortByXPosition( const SCH_REFERENCE& item1, bool SCH_REFERENCE_LIST::sortByXPosition( const SCH_REFERENCE& item1,
const SCH_REFERENCE& item2 ) const SCH_REFERENCE& item2 )
{ {

View File

@ -852,150 +852,45 @@ int DIALOG_BUILD_BOM::PrintComponentsListByRef( FILE* f,
} }
/* Bom Output format option - single part per line int DIALOG_BUILD_BOM::PrintComponentsListByPart( FILE* aFile, SCH_REFERENCE_LIST& aList,
* a common part being defined as have a common value.
* This is true for most designs but will produce an
* incorrect output if two or more parts with the same
* value have different footprints, tolerances, voltage
* rating, etc. Also useful if the following fields
* are edited:
* FIELD1 - manufacture
* FIELD2 - manufacture part number
* FIELD3 - distributor part number
*/
int DIALOG_BUILD_BOM::PrintComponentsListByPart( FILE* f, SCH_REFERENCE_LIST& aList,
bool aIncludeSubComponents ) bool aIncludeSubComponents )
{ {
int qty = 0; int index = 0;
wxString refName; while( index < aList.GetCount() )
wxString fullRefName; // reference + part Id (for multiple parts per package
wxString valName;
#if defined(KICAD_GOST)
wxString footName;
wxString datsName;
#endif
wxString refNames;
wxString lastRef;
wxString unitId;
SCH_COMPONENT* currCmp;
SCH_COMPONENT* nextCmp;
SCH_COMPONENT dummyCmp; // A dummy component, to store fields
for( unsigned ii = 0; ii < aList.GetCount(); ii++ )
{ {
currCmp = aList[ii].GetComponent(); SCH_COMPONENT *component = aList[index].GetComponent();
wxString referenceListStr;
if( ii < aList.GetCount() -1 ) int qty = 1;
nextCmp = aList[ii+1].GetComponent(); referenceListStr.append( aList[index].GetRef() );
else for( unsigned int i = index+1; i < aList.GetCount(); )
nextCmp = NULL;
// Store fields. Store non empty fields only.
for( int jj = FOOTPRINT; jj < currCmp->GetFieldCount(); jj++ )
{ {
// Ensure fields exists in dummy component if( *(aList[i].GetComponent()) == *component )
if( dummyCmp.GetFieldCount() <= jj )
dummyCmp.AddField( *currCmp->GetField( jj ) );
// store useful data
if( !currCmp->GetField( jj )->m_Text.IsEmpty() )
dummyCmp.GetField( jj )->m_Text = currCmp->GetField( jj )->m_Text;
}
refName = aList[ii].GetRef();
valName = currCmp->GetField( VALUE )->m_Text;
#if defined(KICAD_GOST)
footName = currCmp->GetField( FOOTPRINT )->m_Text;
datsName = currCmp->GetField( DATASHEET )->m_Text;
#endif
int multi = 0;
if( aIncludeSubComponents )
{ {
LIB_COMPONENT* entry = CMP_LIBRARY::FindLibraryComponent( currCmp->GetLibName() ); referenceListStr.append( wxT( " " ) + aList[i].GetRef() );
aList.RemoveItem( i );
if( entry )
multi = entry->GetPartCount();
if ( multi <= 1 )
multi = 0;
}
if ( multi && aList[ii].GetUnit() > 0 )
unitId.Printf( wxT("%c"), 'A' -1 + aList[ii].GetUnit() );
else
unitId.Empty();
fullRefName = refName + unitId;
if( refNames.IsEmpty() )
refNames = fullRefName;
else
refNames << wxT( ", " ) << fullRefName;
// In multi parts per package, we have the reference more than once
// but we must count only one package
if( lastRef != refName )
qty++; qty++;
}
lastRef = refName; else
i++; // Increment index only when current item is not removed from the list
// if the next component has same value the line will be printed after.
#if defined(KICAD_GOST)
if( nextCmp && nextCmp->GetField( VALUE )->m_Text.CmpNoCase( valName ) == 0
&& nextCmp->GetField( FOOTPRINT )->m_Text.CmpNoCase( footName ) == 0
&& nextCmp->GetField( DATASHEET )->m_Text.CmpNoCase( datsName ) == 0 )
#else
if( nextCmp && nextCmp->GetField( VALUE )->m_Text.CmpNoCase( valName ) == 0 )
#endif
continue;
// Print line for the current component value:
fprintf( f, "%15s%c%3d", TO_UTF8( valName ), s_ExportSeparatorSymbol, qty );
if( IsFieldChecked(FOOTPRINT ) )
fprintf( f, "%c%15s", s_ExportSeparatorSymbol,
#if defined(KICAD_GOST)
TO_UTF8( footName ) );
#else
TO_UTF8( currCmp->GetField( FOOTPRINT )->m_Text ) );
#endif
#if defined(KICAD_GOST)
fprintf( f, "%c%20s", s_ExportSeparatorSymbol,TO_UTF8( datsName ) );
#endif
// wrap the field in quotes, since it has commas in it.
fprintf( f, "%c\"%s\"", s_ExportSeparatorSymbol, TO_UTF8( refNames ) );
// print fields, on demand
int last_nonempty_field_idx = 0;
for( int jj = FOOTPRINT; jj < dummyCmp.GetFieldCount(); jj++ )
{
if ( !dummyCmp.GetField( jj )->m_Text.IsEmpty() )
last_nonempty_field_idx = jj;
} }
for( int jj = FIELD1; jj <= last_nonempty_field_idx ; jj++ ) // Write value, quantity and list of references
{ fprintf( aFile, "%15s%c%3d%c\"%s\"", TO_UTF8( component->GetField( VALUE )->GetText() ),
if ( IsFieldChecked( jj ) ) s_ExportSeparatorSymbol, qty,
fprintf( f, "%c%4s", s_ExportSeparatorSymbol, s_ExportSeparatorSymbol, TO_UTF8( referenceListStr ) );
TO_UTF8( dummyCmp.GetField( jj )->m_Text ) );
// Write the rest of the fields if required
#if defined( KICAD_GOST )
fprintf( aFile, "%c%20s", s_ExportSeparatorSymbol,
TO_UTF8( component->GetField( DATASHEET )->GetText() ) );
#endif
for( int i = FOOTPRINT; i < component->GetFieldCount(); i++ )
if( IsFieldChecked( i ) )
fprintf( aFile, "%c%15s", s_ExportSeparatorSymbol,
TO_UTF8( component->GetField( i )->GetText() ) );
fprintf( aFile, "\n" );
index++;
} }
fprintf( f, "\n" );
// Clear strings and values, to prepare next component
qty = 0;
refNames.Empty();
for( int jj = FOOTPRINT; jj < dummyCmp.GetFieldCount(); jj++ )
dummyCmp.GetField( jj )->m_Text.Empty();
}
return 0; return 0;
} }

View File

@ -220,6 +220,8 @@ public:
componentFlatList.push_back( aItem ); componentFlatList.push_back( aItem );
} }
void RemoveItem( int aIndex );
/** /**
* Function RemoveSubComponentsFromList * Function RemoveSubComponentsFromList
* Remove sub components from the list, when multiples parts per package are * Remove sub components from the list, when multiples parts per package are

View File

@ -1780,6 +1780,27 @@ bool SCH_COMPONENT::operator <( const SCH_ITEM& aItem ) const
} }
bool SCH_COMPONENT::operator==( const SCH_COMPONENT& aComponent ) const
{
if( GetFieldCount() != aComponent.GetFieldCount() )
return false;
for( int i = VALUE; i < GetFieldCount(); i++ )
{
if( GetField( i )->GetText().Cmp( aComponent.GetField( i )->GetText() ) != 0 )
return false;
}
return true;
}
bool SCH_COMPONENT::operator!=( const SCH_COMPONENT& aComponent ) const
{
return !( *this == aComponent );
}
SCH_ITEM& SCH_COMPONENT::operator=( const SCH_ITEM& aItem ) SCH_ITEM& SCH_COMPONENT::operator=( const SCH_ITEM& aItem )
{ {
wxCHECK_MSG( Type() == aItem.Type(), *this, wxCHECK_MSG( Type() == aItem.Type(), *this,

View File

@ -401,6 +401,9 @@ public:
virtual bool operator <( const SCH_ITEM& aItem ) const; virtual bool operator <( const SCH_ITEM& aItem ) const;
bool operator==( const SCH_COMPONENT& aComponent) const;
bool operator!=( const SCH_COMPONENT& aComponent) const;
SCH_ITEM& operator=( const SCH_ITEM& aItem ); SCH_ITEM& operator=( const SCH_ITEM& aItem );
/** /**