You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
5.6 KiB

15 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2009-2014 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
  5. * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. /* build_BOM_from_board.cpp */
  25. #include <fctsys.h>
  26. #include <confirm.h>
  27. #include <kicad_string.h>
  28. #include <gestfich.h>
  29. #include <pcbnew.h>
  30. #include <pcb_edit_frame.h>
  31. #include <macros.h>
  32. #include <project.h>
  33. #include <wildcards_and_files_ext.h>
  34. #include <class_board.h>
  35. #include <class_module.h>
  36. #include <wx/listimpl.cpp>
  37. /* creates a BOM list rom board
  38. * The format is:
  39. * "Id";"Designator";"Package";"Number";"Designation";"Supplier and ref";
  40. * 1;"P1";"DB25FC";1;"DB25FEMELLE";;;
  41. * 2;"U9";"PGA120";1;"4003APG120";;;
  42. * 3;"JP1";"pin_array_8x2";1;"CONN_8X2";;;
  43. * 4;"RR1";"r_pack9";1;"9x1K";;;
  44. * 5;"X1";"HC-18UH";1;"8MHz";;;
  45. * 6;"U8";"24dip300";1;"EP600";;;
  46. * 7;"U5";"32dip600";1;"628128";;;
  47. * 8;"C2,C3";"C1";2;"47pF";;;
  48. * 9;"U1";"20dip300";1;"74LS245";;;
  49. * 10;"U3";"20dip300";1;"74LS541";;;
  50. * 11;"U2";"20dip300";1;"74LS688";;;
  51. * 12;"C1,C4,C5,C6";"CP6";4;"47uF";;;
  52. */
  53. const wxString CsvFileExtension( wxT( "csv" ) ); // BOM file extension
  54. class cmp
  55. {
  56. public:
  57. wxString m_Ref;
  58. wxString m_Val;
  59. LIB_ID m_fpid;
  60. int m_Id;
  61. int m_CmpCount;
  62. };
  63. WX_DECLARE_LIST( cmp, CmpList );
  64. WX_DEFINE_LIST( CmpList )
  65. void PCB_EDIT_FRAME::RecreateBOMFileFromBoard( wxCommandEvent& aEvent )
  66. {
  67. wxFileName fn;
  68. FILE* fp_bom;
  69. MODULE* module = GetBoard()->m_Modules;
  70. wxString msg;
  71. if( module == NULL )
  72. {
  73. DisplayError( this, _( "Cannot export BOM: there are no footprints in the PCB" ) );
  74. return;
  75. }
  76. /* Set the file extension: */
  77. fn = GetBoard()->GetFileName();
  78. fn.SetExt( CsvFileExtension );
  79. wxString pro_dir = wxPathOnly( Prj().GetProjectFullName() );
  80. wxFileDialog dlg( this, _( "Save Bill of Materials" ), pro_dir,
  81. fn.GetFullName(), CsvFileWildcard(),
  82. wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
  83. if( dlg.ShowModal() == wxID_CANCEL )
  84. return;
  85. fn = dlg.GetPath();
  86. fp_bom = wxFopen( fn.GetFullPath(), wxT( "wt" ) );
  87. if( fp_bom == NULL )
  88. {
  89. msg.Printf( _( "Unable to create file \"%s\"" ), GetChars( fn.GetFullPath() ) );
  90. DisplayError( this, msg );
  91. return;
  92. }
  93. // Write header:
  94. msg = wxT( "\"" );
  95. msg << _( "Id" ) << wxT( "\";\"" );
  96. msg << _( "Designator" ) << wxT( "\";\"" );
  97. msg << _( "Package" ) << wxT( "\";\"" );
  98. msg << _( "Quantity" ) << wxT( "\";\"" );
  99. msg << _( "Designation" ) << wxT( "\";\"" );
  100. msg << _( "Supplier and ref" ) << wxT( "\";\n" );
  101. fprintf( fp_bom, "%s", TO_UTF8( msg ) );
  102. // Build list
  103. CmpList list;
  104. cmp* comp = NULL;
  105. CmpList::iterator iter;
  106. int i = 1;
  107. while( module != NULL )
  108. {
  109. bool valExist = false;
  110. // try to find component in existing list
  111. for( iter = list.begin(); iter != list.end(); ++iter )
  112. {
  113. cmp* current = *iter;
  114. if( (current->m_Val == module->GetValue()) && (current->m_fpid == module->GetFPID()) )
  115. {
  116. current->m_Ref.Append( wxT( ", " ), 1 );
  117. current->m_Ref.Append( module->GetReference() );
  118. current->m_CmpCount++;
  119. valExist = true;
  120. break;
  121. }
  122. }
  123. // If component does not exist yet, create new one and append it to the list.
  124. if( valExist == false )
  125. {
  126. comp = new cmp();
  127. comp->m_Id = i++;
  128. comp->m_Val = module->GetValue();
  129. comp->m_Ref = module->GetReference();
  130. comp->m_fpid = module->GetFPID();
  131. comp->m_CmpCount = 1;
  132. list.Append( comp );
  133. }
  134. // increment module
  135. module = module->Next();
  136. }
  137. // Print list. Also delete temporary created objects.
  138. for( size_t ii = list.GetCount(); ii > 0; ii-- )
  139. {
  140. cmp* current = *list.begin(); // Because the first object will be removed
  141. // from list, all objects will be get here
  142. msg.Empty();
  143. msg << current->m_Id << wxT( ";\"" );
  144. msg << current->m_Ref << wxT( "\";\"" );
  145. msg << FROM_UTF8( current->m_fpid.GetLibItemName().c_str() ) << wxT( "\";" );
  146. msg << current->m_CmpCount << wxT( ";\"" );
  147. msg << current->m_Val << wxT( "\";;;\n" );
  148. fprintf( fp_bom, "%s", TO_UTF8( msg ) );
  149. // We do not need this object, now: remove it from list and delete it
  150. list.DeleteObject( current );
  151. delete (current);
  152. }
  153. fclose( fp_bom );
  154. }