TOOL for renaming parts in STEP file created with PyQt5
2021/04/27 categories:TOOL| tags:TOOL|PyQt5|Python|STEP|QTreeView|
STEP file structure
The STEP file looks like text data, and when you open it with a text editor, it has the following structure.
ISO-10303-21;
HEADER;
...
ENDSEC;
DATA;
...
ENDSEC;
END-ISO-10303-21;
The header part is described in HEADER; … ENDSEC ;, and the data part is described in DATA; … ENDSEC ;. It seems that the part names in the STEP data are included in the data section.
Part name in STEP file
Create a model with a characteristic name for the part name in CAD, export it to a STEP file, open the STEP file with a text editor and search for a character string, as shown below, the part that seems to be the part name Can be found.
DATA;
...
#393=PRODUCT('DDDDDDD','DDDDDDD',' ',(#402));
#394=PRODUCT('CCCCCCC','CCCCCCC',' ',(#403));
#395=PRODUCT('BBBBBB','BBBBBB',' ',(#404));
#396=PRODUCT('AAAAAAA','AAAAAAA',' ',(#405));
...
ENDSEC;
Create a program to get the part name such as’AAAAAAA’ from this item called PRODUCT.
Get the data part from the STEP file
with open(filePath, mode='r') as f:
text = f.read()
The above code will open the STEP data as a text file and store the string in text.
splited = text.split('DATA;\n')
data = splited[1]
The stored character string is divided by’DATA; \ n’, and the second element divided becomes the text data of the data part, and that character string is stored in data.
returnData = {}
for i in data.split(';\n'):
line = i.strip().replace('\n', '')
splitIndex = line.find('=')
lineNumber = line[:splitIndex].strip()
lineText = line[splitIndex + 1:].strip()
dataType = lineText[ : lineText.find('(') ].strip()
if not dataType == '':
dataInner = lineText[ lineText.find('(') + 1 : lineText.rfind(')') ].strip()
datas = [ i.strip().replace("'", '') for i in dataInner.split(',') ]
if dataType == 'PRODUCT':
self.products[lineNumber] = [ dataType, datas ]
returnData[lineNumber] = [ dataType, datas ]
return returnData
You can see that the data is separated by a semicolon line by line and is written in a structure like #number = name (data) ;, so process each data as follows.
- Split string with semicolon
- For one piece of data in ↑, divide by equal
- Divide the second element of the ↑ data by the first appearing parenthesis
- Get the data of PRODUCT with dataType as the first element of ↑ as dataType
- Divide the data part of PRODUCT with a comma and use the first part of the divided data as the part name.
Operation
Source code
import sys
from pathlib import Path
from PyQt5 import QtWidgets, QtCore, QtGui
class StepFileRenamer(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(StepFileRenamer, self).__init__(parent)
self.resize(800, 400)
self.filePath = None
self.model = QtGui.QStandardItemModel(self)
self.view = QtWidgets.QTableView(self)
self.view.setModel(self.model)
self.setCentralWidget( QtWidgets.QWidget(self) )
self.centralWidget().setLayout( QtWidgets.QVBoxLayout() )
self.centralWidget().layout().addWidget(self.view)
self.toolBar = QtWidgets.QToolBar()
self.toolBar.addAction('Open', self.open)
self.toolBar.addAction('Save', self.save)
self.addToolBar(self.toolBar)
def open(self):
filePath, _ = QtWidgets.QFileDialog.getOpenFileName(None, 'Open file', '', 'STEP file(*.stp *.step)')
if filePath == '':
return
with open(filePath, mode='r') as f:
self.step = STEP( f.read() )
self.filePath = Path(filePath)
self.model.clear()
self.model.setHorizontalHeaderLabels(['Before', 'After'])
self.view.setColumnWidth(0, 400)
self.view.horizontalHeader().setStretchLastSection(True)
for lineNumber in self.step.products:
part_name = self.step.products[lineNumber][1][0]
self.model.appendRow([ QtGui.QStandardItem(part_name), QtGui.QStandardItem(part_name) ])
def save(self):
filePath, _ = QtWidgets.QFileDialog.getSaveFileName(None, 'Save file', self.filePath.name, 'STEP file(*.stp )')
if filePath == '':
return
text = self.step.text
for row in range( self.model.rowCount() ):
source, target = self.model.item(row, 0), self.model.item(row, 1)
if not source == target:
text = text.replace( source.text(), target.text() )
with open( Path(filePath).with_suffix('.stp'), mode='w' ) as f:
f.write(text)
class STEP():
class Item():
def __init__(self, name, parent=None):
self.name = name
self.parent = parent
self.children = []
def __init__(self, text):
self.text = text
splited = text.split('DATA;\n')
self.products = {}
self.header = self.loadHeader( splited[0].split('HEADER;\n')[1] )
self.data = self.loadData( splited[1] )
def loadHeader(self, headerText):
return [ i.strip().replace('\n', '') for i in headerText.split(';\n') ]
def loadData(self, dataText):
returnData = {}
for i in dataText.split(';\n'):
line = i.strip().replace('\n', '')
splitIndex = line.find('=')
lineNumber = line[:splitIndex].strip()
lineText = line[splitIndex + 1:].strip()
dataType = lineText[ : lineText.find('(') ].strip()
if not dataType == '':
dataInner = lineText[ lineText.find('(') + 1 : lineText.rfind(')') ].strip()
datas = [ i.strip().replace("'", '') for i in dataInner.split(',') ]
if dataType == 'PRODUCT':
self.products[lineNumber] = [ dataType, datas ]
returnData[lineNumber] = [ dataType, datas ]
return returnData
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
view = StepFileRenamer()
view.show()
app.exec()