清除所有表达式参数

https://forum.freecad.org/viewtopic.php?p=670676
一次性清除所有表达式中的参数,有点保护知识产权的意思。使用前必须备份。

import FreeCAD as App
from PySide import QtCore, QtGui
from PySide.QtGui import QLineEdit, QRadioButton
ExpObjects = []

class ExpressionRemover():
    def __init__(self):

        for i in App.ActiveDocument.Objects:
            if i.isDerivedFrom("Part::Feature"):
                if len(i.ExpressionEngine) != 0:
                    ExpObjects.append(i.Name)
        if len(ExpObjects) == 0:
            App.Console.PrintWarning('There are no Expressions to be removed\n')
        else:
            self.dialog = None
            self.s1 = None

            # Make dialog box
            self.dialog = QtGui.QDialog()
            self.dialog.resize(300,120)
            self.dialog.setWindowTitle("Expression Remover")
            la = QtGui.QVBoxLayout(self.dialog)
            t1 = QtGui.QLabel("Choose to remove All expressions or specific objects in the combobox")
            la.addWidget(t1)

            # Add radio buttons
            self.radio1 = QtGui.QRadioButton("All Object Expressions")
            self.radio2 = QtGui.QRadioButton("Specific Objects")
            self.radio1.clicked.connect(self.on_radio1_clicked)
            self.radio2.clicked.connect(self.on_radio2_clicked)
            # self.radio2.setChecked(True)
            la.addWidget(self.radio1)
            la.addWidget(self.radio2)

            self.expObjs = QtGui.QComboBox()
            self.expObjs.addItems(ExpObjects)

            self.expObjs.setObjectName("expObjs")
            self.expObjs.currentIndexChanged.connect(self.check_validity)

            la.addWidget(self.expObjs)

            # Add OK / Cancel buttons
            self.okbox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
            la.addWidget(self.okbox)
            QtCore.QObject.connect(self.okbox, QtCore.SIGNAL("accepted()"), self.proceed)
            QtCore.QObject.connect(self.okbox, QtCore.SIGNAL("rejected()"), self.close)
            button = self.okbox.button(QtGui.QDialogButtonBox.Ok)
            button.setEnabled(False)
            QtCore.QMetaObject.connectSlotsByName(self.dialog)
            self.dialog.show()
            self.dialog.exec_()

    def check_validity(self,idx):
        App.Console.PrintLog("Current index %d selection changed %s\r\n" % (idx,self.expObjs.currentText()))
        self.radio2.setChecked(True)
        button = self.okbox.button(QtGui.QDialogButtonBox.Ok)
        button.setEnabled(True)

    def on_radio1_clicked(self):
        button = self.okbox.button(QtGui.QDialogButtonBox.Ok)
        button.setEnabled(True)

    def on_radio2_clicked(self):
        button = self.okbox.button(QtGui.QDialogButtonBox.Ok)
        button.setEnabled(True)

    def proceed(self):
        if self.radio1.isChecked():
            for i in App.ActiveDocument.Objects:
                if i.isDerivedFrom("Part::Feature"):
                    if i.ExpressionEngine:
                        for j in i.ExpressionEngine:
                            i.setExpression(j[0], None)
            App.ActiveDocument.recompute()
            self.close()

        if self.radio2.isChecked():
            for i in App.ActiveDocument.Objects:
                if i.Name == self.expObjs.currentText():
                    if i.ExpressionEngine:
                        for j in i.ExpressionEngine:
                            i.setExpression(j[0], None)
            App.ActiveDocument.recompute()
            self.close()

    def close(self):
        self.dialog.hide()

ExpressionRemover()

参数转置

我们之前用的表格参数是竖排,好处是紧凑,但是竖排表格暂时不支持configuration table的下拉菜单,无法自动切换多组参数。
为了方便将竖表参数切换到横表参数,我写了段代码,将模型中的所有参数表达式里的数据链接,由竖表修改为横表,即第2列数据,全部改为第2行数据。
ExpressionTransform()
功能:将表达式中的竖向参数,转换为横向参数,即将表达式里的例如B列数据——B3,B4,B5,B6,转换为第2行横向数据:C2,D2,E2,F2
参考ExpressionRemove()——https://forum.freecad.org/viewtopic.php?p=670676

# doc = App.ActiveDocument
# print(doc.Objects)
# [<body object>, <App::Origin object>, <GeoFeature object>, <GeoFeature object>, <GeoFeature object>, <GeoFeature object>, <GeoFeature object>, <GeoFeature object>, <Sketcher::SketchObject>, <Sheet object>, <PartDesign::Pad>, <Part object>, <App::Origin object>]
# print(doc.Objects[0])
# <body object>
# print(doc.Objects[8].ExpressionEngine)
# [('Constraints[1]', '<<Spreadsheet>>.B3')]
# print(doc.Objects[8].ExpressionEngine[0])
# ('Constraints[1]', '<<Spreadsheet>>.B3')
# print(doc.Objects[10].ExpressionEngine[0])
# ('Length', '<<Spreadsheet>>.B4')

对表达式中列和行进行互换,需要用的方法
原文链接:https://blog.csdn.net/boysoft2002/article/details/119794260

Python Excel表格列数的字母表达与数字的相互转换

本文介绍了Excel表格中列标识与整数之间的转换算法,包括从列标识到整数和反之的转换方法。通过示例展示了如何使用Python内置函数以及自定义函数进行转换,并探讨了不同进制系统的应用。同时,提到了使用openpyxl库进行转换的限制。这些内容对于理解Excel列号的计算原理和编程实现具有指导意义。
摘要由CSDN通过智能技术生成
Excel表格的列数用字母:A,B,C,…,Y,Z,AA,AB,AC,….来表示的,就称它为“列数”。

它的本质就是整数的二十六进制记数,但又有些不一样:若把A看作0,Z之后是AA相当于是“00”,这就是和普通进位制不同的地方。

与普通数制转换的差异

使用内置函数int(x, base=10)转换,把基权设置为26和36进行测试:

>>> int('A',base=26)-int('9',base=26)
1
>>> int('AA',base=26)-int('99',base=26)
27
>>> int('AAA',base=26)-int('999',base=26)
703
>>> int('P',base=26)-int('9',base=26)
16
>>> int('Q',base=26)-int('9',base=26)
Traceback (most recent call last):
  File "<pyshell#194>", line 1, in <module>
    int('Q',base=26)-int('9',base=26)
ValueError: invalid literal for int() with base 26: 'Q'
>>> int('Q',base=36)-9
17
>>> int('Z',base=36)-9
26

普通数制转换从0开始的,10进制以上的数字9以后才用到字母ABC…来代表各位上的数字;而“列数”的表达是从A开始的没有09。通过上面的测试规律可知,对“列数”中出现的字母,分段AP和Q~Z各用26进制和36进制转换,然后乘以各自的位权后累加即可得到结果:

>>> def A2N(s:str)->int:
    ret = 0
    if s[0]>'P': t = int(s[0],base=36)-9
    else: t = int(s[0],base=26)-int('9',base=26)
    ret += t*26**(len(s)-1)
    s = s[1:]
    if s: ret += A2N(s)
    return ret

>>> A2N('A')
1
>>> A2N('AA')
27
>>> A2N('ZY')
701
>>> A2N('ZZ')
702
>>> A2N('AAA')
703
>>> A2N('ZZZ')
18278
>>>

上面这个代码有个好处, 不区分字母大小写,这是因为int()自带的就这样的。以下内容中所有字符串转整数类的函数,如果也要支持小字字母,只需在函数首行位置添加 s=s.upper() 即可实现。

Excel “列数”转成整数

如果不使用现成的int()函数,就按权展开求和,这也是非十进制转化十进制的普遍方法。以下代码的主体就一个return语句,我把按位展开用了一个推导式来完成:

>>> def Col2Int(s:str)->int:
    assert(isinstance(s, str))
    for i in s:
        if not 64<ord(i)<91:
            raise ValueError('Excel Column ValueError')
    return sum([(ord(n)-64)*26**i for i,n in enumerate(list(s)[::-1])])

>>> Col2Int('A')
1
>>> Col2Int('Z')
26
>>> Col2Int('AA')
27
>>> Col2Int('ZZ')
702
>>> Col2Int('ZJX')
17860
>>> Col2Int('ZZZ')
18278
>>> 26*26**2+26*26+26
18278
>>> Col2Int('ABCD')
19010
>>> 1*26**3+2*26**2+3*26**1+4*26**0
19010
>>>

整数转换成“列数”

反过来整数转非十进制数的普遍方法是反复“除权求余”获取各位上的数字,先建一个字母列表 [‘A’, ‘B’, ‘C’, …., ‘Z’] 用于映射各位上的“数字”:

>>> def ExcelColumn(n:int)->str:
    assert(isinstance(n, int) and n>0)
    num = [chr(i) for i in range(65,91)]
    ret = []
    while n>0:
        n,m = divmod(n-1, len(num))
        ret.append(num[m])
    return ''.join(ret[::-1])

>>> ExcelColumn(703)
'AAA'
>>> ExcelColumn(26**2+26+1)
'AAA'
>>> ExcelColumn(5*26**4+4*26**3+3*26**2+2*26**1+1*26**0)
'EDCBA'
>>> 5*26**4+4*26**3+3*26**2+2*26**1+1*26**0
2357265
>>> ExcelColumn(2357265)
'EDCBA'
>>>

或者不建列表,各位分别转换;和上段代码一样其中的 (n-1) 非常关键,原因是“列数”中没有“零”而是从“一”开始的,同样没有“10”直接从“Z”跳到“AA”:

>>> def num2chr(n:int)->str:
    ret = ''
    while n//26:
        n,m = divmod(n-1,26)
        ret += chr(65+m)
    if n: ret += chr(65+n-1)
    return ret[::-1]

递归法实现转换

>>> def ExcelColumn(n:int)->str:
    num = [chr(i) for i in range(65,91)]
    ret,(n,m) = '',divmod(n-1,26)
    if n: ret += ExcelColumn(n)
    ret += num[m]
    return ret

>>> ExcelColumn(1)
'A'
>>> ExcelColumn(26)
'Z'
>>> ExcelColumn(27)
'AA'
>>> ExcelColumn(702)
'ZZ'
>>> ExcelColumn(703)
'AAA'
>>>
>>>
>>> def Col2Int(s:str)->int:
    ret=0
    ret += (ord(s[0])-64)*26**(len(s)-1)
    s = s[1:]
    if s: ret += Col2Int(s)
    return ret

>>> Col2Int('Z')
26
>>> Col2Int('AA')
27
>>> Col2Int('XFD')
16384
>>> Col2Int('ILOVEYOU')
76181660199
>>> Col2Int('HANNYANG')
64736574559
>>>

用第三方库函数转换

需要安装openpyxl库,另外它限制了“列数”最大值为三位字母,实际上 Excel2007+ 的列数最大值是16384 (是XFD并非ZZZ),而EXCEL2003等老版本的最大列数只有256。

>>> from openpyxl.utils import get_column_letter as ExcelColumn
>>> from openpyxl.utils import column_index_from_string as Col2Int
>>>
>>> ExcelColumn(18278)
'ZZZ'
>>> ExcelColumn(17376)
'YRH'
>>>
>>> Col2Int('XFD')
16384
>>> Col2Int('ZZZ')
18278
>>> Col2Int('AAAA')
Traceback (most recent call last):
  File "D:\Python38-32\lib\site-packages\openpyxl\utils\cell.py", line 121, in column_index_from_string
    return _COL_STRING_CACHE[str_col.upper()]
KeyError: 'AAAA'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#127>", line 1, in <module>
    Col2Int('AAAA')
  File "D:\Python38-32\lib\site-packages\openpyxl\utils\cell.py", line 123, in column_index_from_string
    raise ValueError("{0} is not a valid column name".format(str_col))
ValueError: AAAA is not a valid column name
>>>

leetcode题号168和171

Excel Sheet Column Title
Given a positive integer, return its corresponding column title as appear in an Excel sheet. [#168]

Excel Sheet Column Number
Given a column title as appear in an Excel sheet, return its corresponding column number. [#171]

作者:秦晓川  创建时间:2024-03-19 11:16
最后编辑:秦晓川  更新时间:2024-09-15 10:02
上一篇:
下一篇: