Make single part per line BOM generation compare all component fields.
This commit is contained in:
parent
0a68744e2d
commit
97884551f0
|
@ -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 )
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue