-
-
Save 3bagorion33/2b2e7ef77143d84e4eadc90d45255f4a to your computer and use it in GitHub Desktop.
This is an Altium DelphiScript that creates pin functions from a CSV file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| {******************************************************************************* | |
| * CSV2Functions - Altium Designer Script | |
| * | |
| * Purpose: Imports pin names and functions from a CSV file and applies them | |
| * to the currently selected schematic component in a library. | |
| * | |
| * CSV Format Expected: | |
| * - Column 1: Pin designator (e.g., "1", "A1", "B2") | |
| * - Column 2: New pin name (e.g., "VCC", "GND", "DATA") | |
| * - Column 3: Pin functions (e.g., "Power/Input", "Ground", "I/O") | |
| * | |
| * Example CSV content: | |
| * 1,VCC,Power | |
| * 2,GND,Ground | |
| * 3,DATA,I/O/Digital | |
| * | |
| * Contributors: Chris Harrison, René HENKE | |
| *******************************************************************************} | |
| Procedure CSV2Functions; | |
| Var | |
| // Altium document and component references | |
| SchLib: ISch_Lib; // Reference to the schematic library document | |
| SchComponent: ISch_Component; // Reference to the current component being edited | |
| // File handling variables | |
| OpenDialog: TOpenDialog; // Dialog for CSV file selection | |
| PinList: TStringList; // List to store parsed CSV entries | |
| PinEntry: string; // Individual entry from the pin list | |
| // CSV parsing variables | |
| CSVFile: File; // File handle for the CSV file | |
| CSVLine: string; // Current line being read from CSV | |
| PinName: string; // Pin designator from the component | |
| PinPropList: string; // Properties extracted from CSV (name + functions) | |
| PinFunctions: string; // Pin functions extracted from CSV | |
| NewPinName: string; // New pin name to be applied | |
| // Loop and position tracking variables | |
| i, j: Integer; // Loop counters | |
| DelimiterPosName: Integer; // Position of delimiter between pin designator and name | |
| DelimiterPosFct: Integer; // Position of delimiter between name and functions | |
| DelimiterPos: Integer; // General delimiter position for CSV parsing | |
| // Pin iteration variables | |
| PinIterator: ISch_Iterator; // Iterator for traversing component pins | |
| PinItem: ISch_Line; // Current pin being processed | |
| NoOfEntrys: Integer; // Number of entries (currently unused) | |
| Begin | |
| {*************************************************************************** | |
| * STEP 1: Validate the current document and component | |
| **************************************************************************} | |
| // Get reference to the currently active schematic library document | |
| SchLib := SchServer.GetCurrentSchDocument; | |
| // Ensure we're working with a valid schematic library document | |
| if SchLib = Nil Then | |
| begin | |
| ShowError('Script must be run from an SchLib document.'); | |
| Exit; | |
| end; | |
| // Double-check that the document is actually a schematic library | |
| if (SchLib.ObjectID <> eSchLib) Then | |
| begin | |
| ShowError('Document is not an SchLib.'); | |
| Exit; | |
| end; | |
| // Get reference to the currently selected component in the library | |
| SchComponent := SchLib.CurrentSchComponent; | |
| // Ensure a component is currently selected/open for editing | |
| if SchComponent = nil then | |
| begin | |
| ShowError('No schematic symbol currently open.'); | |
| Exit; | |
| end; | |
| {*************************************************************************** | |
| * STEP 2: Get CSV file from user | |
| **************************************************************************} | |
| // Create and configure file selection dialog | |
| OpenDialog := TOpenDialog.Create(nil); | |
| try | |
| // Set up the file dialog to filter for CSV files | |
| OpenDialog.Filter := 'CSV Files|*.csv|All Files|*.*'; | |
| OpenDialog.Title := 'Select CSV File'; | |
| // Show the dialog and exit if user cancels | |
| if not OpenDialog.Execute then | |
| begin | |
| ShowError('No CSV file selected.'); | |
| Exit; | |
| end; | |
| {************************************************************************* | |
| * STEP 3: Parse the CSV file and store pin data | |
| ************************************************************************} | |
| // Initialize string list to store parsed CSV entries | |
| PinList := TStringList.Create; | |
| try | |
| // Open the selected CSV file for reading | |
| try | |
| AssignFile(CSVFile, OpenDialog.FileName); | |
| Reset(CSVFile); | |
| except | |
| Raise('Error opening file: ' + OpenDialog.FileName); | |
| end; | |
| // Read and parse each line of the CSV file | |
| while not Eof(CSVFile) do | |
| begin | |
| Readln(CSVFile, CSVLine); | |
| // Look for comma delimiter (basic CSV parsing) | |
| DelimiterPos := Pos(',', CSVLine); | |
| if DelimiterPos > 0 then | |
| begin | |
| // Convert CSV format (comma-separated) to internal format (slash-separated) | |
| // This makes it easier to parse later: "1,VCC,Power" becomes "1/VCC/Power" | |
| PinList.Add(AnsiReplaceText(CSVLine, ',', '/')); | |
| end; | |
| end; | |
| // Close the CSV file as we're done reading | |
| CloseFile(CSVFile); | |
| {********************************************************************* | |
| * STEP 4: Apply pin data to component pins | |
| ********************************************************************} | |
| // Create iterator to traverse all pins in the component | |
| PinIterator := SchComponent.SchIterator_Create; | |
| PinIterator.AddFilter_ObjectSet(MkSet(ePin)); | |
| // Start iterating through each pin in the component | |
| PinItem := PinIterator.FirstSchObject; | |
| while PinItem <> Nil Do | |
| begin | |
| // Get the current pin's designator (e.g., "1", "A1", "B2") | |
| PinName := PinItem.GetState_Designator; | |
| // Search through our CSV data for a matching pin designator | |
| for j := 0 to PinList.Count - 1 do | |
| begin | |
| PinEntry := PinList[j]; | |
| // Check if this CSV entry starts with our pin designator | |
| // Format expected: "PinDesignator/PinName/Functions" | |
| if StartsText(PinName + '/', PinList[j]) then | |
| begin | |
| // Extract everything after the pin designator | |
| DelimiterPosName := Pos('/', PinList[j]); | |
| PinPropList := Copy(PinList[j], DelimiterPosName + 1, Length(PinList[j]) - DelimiterPosName); | |
| // Look for another delimiter to separate name from functions | |
| DelimiterPosFct := Pos('/', PinPropList); | |
| if DelimiterPosFct > 0 then | |
| begin | |
| // Case 1: We have both pin name AND functions | |
| // Extract the new pin name (between first and second slash) | |
| NewPinName := Copy(PinPropList, 1, DelimiterPosFct - 1); | |
| // Extract the pin functions (everything after second slash) | |
| PinFunctions := Copy(PinPropList, DelimiterPosFct + 1, Length(PinPropList) - DelimiterPosFct); | |
| // Remove trailing slash if present | |
| if AnsiEndsStr('/', PinFunctions) then | |
| PinFunctions := Copy(PinFunctions, 1, Length(PinFunctions) - 1); | |
| // Apply the functions first by setting them as the name temporarily | |
| PinItem.SetState_Name(PinFunctions + '/'); | |
| PinItem.SetState_FunctionsFromName; // Parse functions from the name | |
| // Then set the actual pin name | |
| PinItem.SetState_Name(NewPinName); | |
| end | |
| else | |
| begin | |
| // Case 2: We only have a pin name, no functions specified | |
| NewPinName := PinPropList; | |
| // Clear any existing functions first (does not work) | |
| PinItem.SetState_Name(''); | |
| PinItem.SetState_FunctionsFromName; // Apply empty functions | |
| // Set the new pin name | |
| PinItem.SetState_Name(NewPinName); | |
| end; | |
| // Update the visual representation of the pin | |
| PinItem.GraphicallyInvalidate; | |
| // Break out of the search loop as we found our match | |
| break; | |
| end; | |
| end; | |
| // Move to the next pin in the component | |
| PinItem := PinIterator.NextSchObject; | |
| end; | |
| {********************************************************************* | |
| * STEP 5: Clean up and finalize changes | |
| ********************************************************************} | |
| // Clean up the pin iterator | |
| SchComponent.SchIterator_Destroy(PinIterator); | |
| // Refresh the visual display of the entire library | |
| SchLib.GraphicallyInvalidate; | |
| // Process the changes through Altium's change management system | |
| SchServer.ProcessControl.PreProcess(SchLib, ''); | |
| SchServer.ProcessControl.PostProcess(SchLib, ''); | |
| // Notify user of successful completion | |
| ShowMessage('Pin functions updated successfully.'); | |
| finally | |
| // Always clean up the pin list, even if an error occurred | |
| PinList.Free; | |
| end; | |
| finally | |
| // Always clean up the file dialog, even if an error occurred | |
| OpenDialog.Free; | |
| end; | |
| End; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment