ComfyUI_StringOps
StringOps is a versatile text processing toolkit built for ComfyUI's node-based workflows.
This commit is contained in:
@@ -1,2 +1,16 @@
|
||||
# ComfyUI_StringOps
|
||||
StringOps is a versatile text processing toolkit built for ComfyUI's node-based workflows."
|
||||
#[ComfyUI_StringOps]#
|
||||
StringOps is a versatile text processing toolkit built for ComfyUI's node-based workflows.
|
||||
|
||||
|
||||
#Install
|
||||
cd ComfyUI/custom_nodes
|
||||
git clone https://github.com/MeeeyoAI/ComfyUI_StringOps.git
|
||||
Or download the zip file and extracted, copy the resulting folder to ComfyUI\custom_ Nodes
|
||||
Restart ComfyUI.
|
||||
|
||||
|
||||
#About me
|
||||
- [bilibili]:https://space.bilibili.com/3546690300676691
|
||||
- [博主主页]:http://www.meeeyo.com
|
||||
- [知识星球]:https://t.zsxq.com/ufSS2
|
||||
|
||||
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
from .meyo_node_Computational import StandardSize, CompareInt, FloatToInteger, GenerateNumbers, GetRandomIntegerInRange
|
||||
from .meyo_node_String import AddPrefixSuffix, ExtractSubstring, ExtractSubstringByIndices, SplitStringByDelimiter, ProcessString, ExtractBeforeAfter, ReplaceNthOccurrence, BatchReplaceStrings, ReplaceMultiple, RandomLineFromText, CheckSubstringPresence, AddPrefixSuffixToLines, ExtractAndCombineLines, FilterLinesBySubstrings, FilterLinesByWordCount, SplitAndExtractText, CountOccurrences, ExtractLinesByIndex, ExtractSpecificLines, RemoveContentBetweenChars, ShuffleTextLines, ConditionalTextOutput, TextConditionCheck, TextConcatenation, ExtractSpecificData, FindFirstLineContent
|
||||
from .meyo_node_File import FileListAndSuffix, ReadExcelData, WriteExcelData, FindExcelData, ReadExcelRowOrColumnDiff
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
|
||||
#运算型节点:meyo_node_Computational
|
||||
"StandardSize": StandardSize,
|
||||
"CompareInt": CompareInt,
|
||||
"FloatToInteger": FloatToInteger,
|
||||
"GenerateNumbers": GenerateNumbers,
|
||||
"GetRandomIntegerInRange": GetRandomIntegerInRange,
|
||||
|
||||
#字符串处理:meyo_node_String
|
||||
"AddPrefixSuffix": AddPrefixSuffix,
|
||||
"ExtractSubstring": ExtractSubstring,
|
||||
"ExtractSubstringByIndices": ExtractSubstringByIndices,
|
||||
"SplitStringByDelimiter": SplitStringByDelimiter,
|
||||
"ProcessString": ProcessString,
|
||||
"ExtractBeforeAfter": ExtractBeforeAfter,
|
||||
"ReplaceNthOccurrence": ReplaceNthOccurrence,
|
||||
"ReplaceMultiple": ReplaceMultiple,
|
||||
"BatchReplaceStrings": BatchReplaceStrings,
|
||||
"RandomLineFromText": RandomLineFromText,
|
||||
"CheckSubstringPresence": CheckSubstringPresence,
|
||||
"AddPrefixSuffixToLines": AddPrefixSuffixToLines,
|
||||
"ExtractAndCombineLines": ExtractAndCombineLines,
|
||||
"FilterLinesBySubstrings": FilterLinesBySubstrings,
|
||||
"FilterLinesByWordCount": FilterLinesByWordCount,
|
||||
"SplitAndExtractText": SplitAndExtractText,
|
||||
"CountOccurrences": CountOccurrences,
|
||||
"ExtractLinesByIndex": ExtractLinesByIndex,
|
||||
"ExtractSpecificLines": ExtractSpecificLines,
|
||||
"RemoveContentBetweenChars": RemoveContentBetweenChars,
|
||||
"ShuffleTextLines": ShuffleTextLines,
|
||||
"ConditionalTextOutput": ConditionalTextOutput,
|
||||
"TextConditionCheck": TextConditionCheck,
|
||||
"TextConcatenation": TextConcatenation,
|
||||
"ExtractSpecificData": ExtractSpecificData,
|
||||
"FindFirstLineContent": FindFirstLineContent,
|
||||
|
||||
#文件处理:meyo_node_File
|
||||
"FileListAndSuffix": FileListAndSuffix,
|
||||
"ReadExcelData": ReadExcelData,
|
||||
"WriteExcelData": WriteExcelData,
|
||||
"FindExcelData": FindExcelData,
|
||||
"ReadExcelRowOrColumnDiff": ReadExcelRowOrColumnDiff,
|
||||
|
||||
}
|
||||
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
|
||||
#运算型节点:meyo_node_Computational
|
||||
"StandardSize": "重置尺寸(meeeyo.com)",
|
||||
"CompareInt": "比较数值(meeeyo.com)",
|
||||
"FloatToInteger": "规范数值(meeeyo.com)",
|
||||
"GenerateNumbers": "生成范围数组(meeeyo.com)",
|
||||
"GetRandomIntegerInRange": "范围内随机数(meeeyo.com)",
|
||||
|
||||
#字符串处理:meyo_node_String
|
||||
"AddPrefixSuffix": "添加前后缀(meeeyo.com)",
|
||||
"ExtractSubstring": "提取标签之间(meeeyo.com)",
|
||||
"ExtractSubstringByIndices": "按数字范围提取(meeeyo.com)",
|
||||
"SplitStringByDelimiter": "分隔符拆分两边(meeeyo.com)",
|
||||
"ProcessString": "常规处理字符(meeeyo.com)",
|
||||
"ExtractBeforeAfter": "提取前后字符(meeeyo.com)",
|
||||
"ReplaceNthOccurrence": "替换第n次出现(meeeyo.com)",
|
||||
"ReplaceMultiple": "多次出现依次替换(meeeyo.com)",
|
||||
"BatchReplaceStrings": "批量替换字符(meeeyo.com)",
|
||||
"RandomLineFromText": "随机行内容(meeeyo.com)",
|
||||
"CheckSubstringPresence": "判断是否包含字符(meeeyo.com)",
|
||||
"AddPrefixSuffixToLines": "段落每行添加前后缀(meeeyo.com)",
|
||||
"ExtractAndCombineLines": "段落提取指定索引行(meeeyo.com)",
|
||||
"FilterLinesBySubstrings": "段落提取或移除字符行(meeeyo.com)",
|
||||
"FilterLinesByWordCount": "段落字数条件过滤行(meeeyo.com)",
|
||||
"SplitAndExtractText": "按序号提取分割文本(meeeyo.com)",
|
||||
"CountOccurrences": "文本出现次数(meeeyo.com)",
|
||||
"ExtractLinesByIndex": "文本拆分(meeeyo.com)",
|
||||
"ExtractSpecificLines": "提取特定行(meeeyo.com)",
|
||||
"RemoveContentBetweenChars": "删除标签内的内容(meeeyo.com)",
|
||||
"ShuffleTextLines": "随机打乱(meeeyo.com)",
|
||||
"ConditionalTextOutput": "判断返回内容(meeeyo.com)",
|
||||
"TextConditionCheck": "文本按条件判断(meeeyo.com)",
|
||||
"TextConcatenation": "文本组合(meeeyo.com)",
|
||||
"ExtractSpecificData": "提取多层指定数据(meeeyo.com)",
|
||||
"FindFirstLineContent": "指定字符行参数(meeeyo.com)",
|
||||
|
||||
#文件处理:meyo_node_File
|
||||
"FileListAndSuffix": "从路径加载(meeeyo.com)",
|
||||
"ReadExcelData": "读取表格数据(meeeyo.com)",
|
||||
"WriteExcelData": "写入表格数据(meeeyo.com)",
|
||||
"FindExcelData": "查找表格数据(meeeyo.com)",
|
||||
"ReadExcelRowOrColumnDiff": "读取表格数量差(meeeyo.com)",
|
||||
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
import math
|
||||
import random
|
||||
|
||||
|
||||
|
||||
|
||||
#======宽度高度调整
|
||||
class StandardSize:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"width": ("INT",),
|
||||
"height": ("INT",),
|
||||
"size_option": (["小尺寸", "中尺寸", "大尺寸"], {"default": "中尺寸"}), # 下拉选择框
|
||||
},
|
||||
"optional": {},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT", "INT")
|
||||
FUNCTION = "resize_image"
|
||||
CATEGORY = "Meyo/Image"
|
||||
|
||||
def resize_image(self, width, height, size_option):
|
||||
# 根据选择的选项调整尺寸像尺寸
|
||||
if size_option == "小尺寸":
|
||||
if width / height >= 1.23:
|
||||
return (768, 512)
|
||||
elif 0.82 < width / height < 1.23:
|
||||
return (768, 768)
|
||||
else:
|
||||
return (512, 768)
|
||||
elif size_option == "中尺寸":
|
||||
if width / height >= 1.23:
|
||||
return (1216, 832)
|
||||
elif 0.82 < width / height < 1.23:
|
||||
return (1216, 1216)
|
||||
else:
|
||||
return (832, 1216)
|
||||
elif size_option == "大尺寸":
|
||||
if width / height >= 1.23:
|
||||
return (1600, 1120)
|
||||
elif 0.82 < width / height < 1.23:
|
||||
return (1600, 1600)
|
||||
else:
|
||||
return (1120, 1600)
|
||||
|
||||
|
||||
|
||||
#======比较数值
|
||||
class CompareInt:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"input_float": ("FLOAT", {"default": 4.0}),
|
||||
"range": ("STRING", {"default": "3.5-5.5"}),
|
||||
},
|
||||
"optional": {},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
FUNCTION = "compare_float_to_range"
|
||||
CATEGORY = "Meeeyo/Number"
|
||||
|
||||
def compare_float_to_range(self, input_float, range):
|
||||
try:
|
||||
if '-' in range:
|
||||
lower_bound, upper_bound = map(float, range.split('-'))
|
||||
else:
|
||||
lower_bound = upper_bound = float(range)
|
||||
if input_float < lower_bound:
|
||||
return ("小",)
|
||||
elif input_float > upper_bound:
|
||||
return ("大",)
|
||||
else:
|
||||
return ("中",)
|
||||
except ValueError:
|
||||
return ("Error: Invalid input format.",)
|
||||
|
||||
#======规范数值
|
||||
class FloatToInteger:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"float_value": ("FLOAT", {"default": 3.14}),
|
||||
"operation": (["四舍五入", "取大值", "取小值", "最近32倍"], {"default": "四舍五入"}),
|
||||
},
|
||||
"optional": {},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
FUNCTION = "convert_float_to_integer"
|
||||
CATEGORY = "Meeeyo/Number"
|
||||
|
||||
def IS_CHANGED():
|
||||
return float("NaN")
|
||||
|
||||
def convert_float_to_integer(self, float_value, operation):
|
||||
if operation == "四舍五入":
|
||||
result = round(float_value)
|
||||
elif operation == "取大值":
|
||||
result = math.ceil(float_value)
|
||||
elif operation == "取小值":
|
||||
result = math.floor(float_value)
|
||||
elif operation == "最近32倍":
|
||||
result = round(float_value / 32) * 32
|
||||
return (result,)
|
||||
|
||||
|
||||
#======生成范围数组
|
||||
class GenerateNumbers:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"range_rule": ("STRING", {"default": "3|1-10"}),
|
||||
"mode": (["顺序", "随机"], {"default": "顺序"}),
|
||||
"prefix_suffix": ("STRING", {"default": "|"}),
|
||||
},
|
||||
"optional": {},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
FUNCTION = "generate_numbers"
|
||||
CATEGORY = "Meeeyo/Number"
|
||||
|
||||
def IS_CHANGED():
|
||||
return float("NaN")
|
||||
|
||||
def generate_numbers(self, range_rule, mode, prefix_suffix):
|
||||
try:
|
||||
start_str, range_str = range_rule.split('|')
|
||||
start = int(start_str)
|
||||
end_range = list(map(int, range_str.split('-')))
|
||||
if len(end_range) == 1:
|
||||
end = end_range[0]
|
||||
numbers = [str(i).zfill(start) for i in range(1, end + 1)]
|
||||
else:
|
||||
start_range, end = end_range
|
||||
numbers = [str(i).zfill(start) for i in range(start_range, end + 1)]
|
||||
if prefix_suffix.strip():
|
||||
prefix, suffix = prefix_suffix.split('|')
|
||||
else:
|
||||
prefix, suffix = "", ""
|
||||
if mode == "随机":
|
||||
random.shuffle(numbers)
|
||||
numbers = [f"{prefix}{num}{suffix}" for num in numbers]
|
||||
result = '\n'.join(numbers)
|
||||
return (result,)
|
||||
except ValueError:
|
||||
return ("",)
|
||||
|
||||
|
||||
#======范围内随机数
|
||||
class GetRandomIntegerInRange:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"range_str": ("STRING", {"default": "0-10"}),
|
||||
},
|
||||
"optional": {},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT", "STRING")
|
||||
FUNCTION = "get_random_integer_in_range"
|
||||
CATEGORY = "Meeeyo/Number"
|
||||
|
||||
def IS_CHANGED():
|
||||
return float("NaN")
|
||||
|
||||
def get_random_integer_in_range(self, range_str):
|
||||
try:
|
||||
start, end = map(int, range_str.split('-'))
|
||||
if start > end:
|
||||
start, end = end, start
|
||||
random_int = random.randint(start, end)
|
||||
return (random_int, str(random_int))
|
||||
except ValueError:
|
||||
return (0, "0")
|
||||
@@ -0,0 +1,315 @@
|
||||
import csv
|
||||
import openpyxl
|
||||
import os
|
||||
|
||||
#======文件路径和后缀统计
|
||||
class FileListAndSuffix:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"folder_path": ("STRING",),
|
||||
"file_extension": (["jpg", "png", "jpg&png", "txt", "csv", "all"], {"default": "jpg"}),
|
||||
},
|
||||
"optional": {},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "INT", "LIST")
|
||||
FUNCTION = "file_list_and_suffix"
|
||||
CATEGORY = "Meeeyo/File"
|
||||
|
||||
def IS_CHANGED():
|
||||
return float("NaN")
|
||||
|
||||
def file_list_and_suffix(self, folder_path, file_extension):
|
||||
try:
|
||||
if not os.path.isdir(folder_path):
|
||||
return ("", 0, [])
|
||||
|
||||
if file_extension == "all":
|
||||
file_paths = [os.path.join(folder_path, f) for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))]
|
||||
elif file_extension == "jpg&png":
|
||||
file_paths = [os.path.join(folder_path, f) for f in os.listdir(folder_path) if f.lower().endswith(('.jpg', '.png'))]
|
||||
else:
|
||||
file_paths = [os.path.join(folder_path, f) for f in os.listdir(folder_path) if f.lower().endswith('.' + file_extension)]
|
||||
|
||||
return ('\n'.join(file_paths), len(file_paths), file_paths)
|
||||
except Exception as e:
|
||||
return ("", 0, [])
|
||||
|
||||
|
||||
#======读取表格数据
|
||||
class ReadExcelData:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"excel_path": ("STRING", {"default": "path/to/your/file.xlsx"}),
|
||||
"sheet_name": ("STRING", {"default": "Sheet1"}),
|
||||
"row_range": ("STRING", {"default": "2-3"}),
|
||||
"col_range": ("STRING", {"default": "1-4"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
FUNCTION = "read_excel_data"
|
||||
CATEGORY = "Meeeyo/File"
|
||||
|
||||
def IS_CHANGED():
|
||||
return float("NaN")
|
||||
|
||||
def read_excel_data(self, excel_path, sheet_name, row_range, col_range):
|
||||
try:
|
||||
if "-" in row_range:
|
||||
start_row, end_row = map(int, row_range.split("-"))
|
||||
else:
|
||||
start_row = end_row = int(row_range)
|
||||
|
||||
if "-" in col_range:
|
||||
start_col, end_col = map(int, col_range.split("-"))
|
||||
else:
|
||||
start_col = end_col = int(col_range)
|
||||
|
||||
start_row = max(1, start_row)
|
||||
start_col = max(1, start_col)
|
||||
|
||||
workbook = openpyxl.load_workbook(excel_path, read_only=True, data_only=True)
|
||||
sheet = workbook[sheet_name]
|
||||
|
||||
output_lines = []
|
||||
for row in range(start_row, end_row + 1):
|
||||
row_data = []
|
||||
for col in range(start_col, end_col + 1):
|
||||
cell_value = sheet.cell(row=row, column=col).value
|
||||
row_data.append(str(cell_value) if cell_value is not None else "")
|
||||
output_lines.append("|".join(row_data))
|
||||
|
||||
workbook.close()
|
||||
del workbook
|
||||
|
||||
return ("\n".join(output_lines),)
|
||||
|
||||
except Exception as e:
|
||||
return (f"Error: {str(e)}",)
|
||||
|
||||
|
||||
#======写入表格数据
|
||||
class WriteExcelData:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"excel_path": ("STRING", {"default": "path/to/your/file.xlsx"}),
|
||||
"sheet_name": ("STRING", {"default": "Sheet1"}),
|
||||
"row_range": ("STRING", {"default": "2-3"}),
|
||||
"col_range": ("STRING", {"default": "1-4"}),
|
||||
"data": ("STRING", {"default": "", "multiline": True}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
FUNCTION = "write_excel_data"
|
||||
CATEGORY = "Meeeyo/File"
|
||||
|
||||
def IS_CHANGED():
|
||||
return float("NaN")
|
||||
|
||||
def write_excel_data(self, excel_path, sheet_name, row_range, col_range, data):
|
||||
try:
|
||||
if not os.path.exists(excel_path):
|
||||
return (f"Error: File does not exist at path: {excel_path}",)
|
||||
|
||||
if not os.access(excel_path, os.W_OK):
|
||||
return (f"Error: No write permission for file at path: {excel_path}",)
|
||||
|
||||
if "-" in row_range:
|
||||
start_row, end_row = map(int, row_range.split("-"))
|
||||
else:
|
||||
start_row = end_row = int(row_range)
|
||||
|
||||
if "-" in col_range:
|
||||
start_col, end_col = map(int, col_range.split("-"))
|
||||
else:
|
||||
start_col = end_col = int(col_range)
|
||||
|
||||
start_row = max(1, start_row)
|
||||
start_col = max(1, start_col)
|
||||
|
||||
workbook = openpyxl.load_workbook(excel_path, read_only=False, data_only=True)
|
||||
sheet = workbook[sheet_name]
|
||||
|
||||
data_lines = data.strip().split("\n")
|
||||
|
||||
for row_index, line in enumerate(data_lines, start=start_row):
|
||||
if row_index > end_row:
|
||||
break
|
||||
|
||||
cell_values = line.split("|")
|
||||
for col_index, cell_value in enumerate(cell_values, start=start_col):
|
||||
if col_index > end_col:
|
||||
break
|
||||
|
||||
if cell_value.strip():
|
||||
sheet.cell(row=row_index, column=col_index).value = cell_value.strip()
|
||||
|
||||
workbook.save(excel_path)
|
||||
|
||||
workbook.close()
|
||||
del workbook
|
||||
|
||||
return ("Data written successfully!",)
|
||||
|
||||
except PermissionError as pe:
|
||||
return (f"Permission Error: {str(pe)}",)
|
||||
except Exception as e:
|
||||
return (f"Error: {str(e)}",)
|
||||
|
||||
|
||||
#======查找表格数据
|
||||
class FindExcelData:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"excel_path": ("STRING", {"default": "path/to/your/file.xlsx"}),
|
||||
"sheet_name": ("STRING", {"default": "Sheet1"}),
|
||||
"search_content": ("STRING", {"default": "查找内容"}),
|
||||
"search_mode": (["精确查找", "模糊查找"], {"default": "精确查找"}),
|
||||
},
|
||||
"optional": {},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "INT", "INT")
|
||||
FUNCTION = "find_excel_data"
|
||||
CATEGORY = "Meeeyo/File"
|
||||
|
||||
def IS_CHANGED():
|
||||
return float("NaN")
|
||||
|
||||
def find_excel_data(self, excel_path, sheet_name, search_content, search_mode):
|
||||
try:
|
||||
if not os.path.exists(excel_path):
|
||||
return (f"Error: File does not exist at path: {excel_path}", None, None)
|
||||
|
||||
if not os.access(excel_path, os.R_OK):
|
||||
return (f"Error: No read permission for file at path: {excel_path}", None, None)
|
||||
|
||||
workbook = openpyxl.load_workbook(excel_path, read_only=True, data_only=True)
|
||||
sheet = workbook[sheet_name]
|
||||
|
||||
results = []
|
||||
found_row = None
|
||||
found_col = None
|
||||
|
||||
for row in range(1, sheet.max_row + 1):
|
||||
for col in range(1, sheet.max_column + 1):
|
||||
cell = sheet.cell(row=row, column=col)
|
||||
cell_value = cell.value if cell.value is not None else ""
|
||||
|
||||
if (search_mode == "精确查找" and cell_value == search_content) or \
|
||||
(search_mode == "模糊查找" and search_content in cell_value):
|
||||
results.append(f"{sheet_name}|{row}|{col}|{cell_value}")
|
||||
found_row = row
|
||||
found_col = col
|
||||
|
||||
workbook.close()
|
||||
del workbook
|
||||
|
||||
if not results:
|
||||
return ("No results found.", None, None)
|
||||
|
||||
return ("\n".join(results), found_row, found_col)
|
||||
|
||||
except Exception as e:
|
||||
return (f"Error: {str(e)}", None, None)
|
||||
|
||||
|
||||
#======读取表格数量差
|
||||
class ReadExcelRowOrColumnDiff:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"excel_path": ("STRING", {"default": "path/to/your/file.xlsx"}),
|
||||
"sheet_name": ("STRING", {"default": "Sheet1"}),
|
||||
"read_mode": (["读行", "读列"], {"default": "读行"}),
|
||||
"indices": ("STRING", {"default": "1,3"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
FUNCTION = "read_excel_row_or_column_diff"
|
||||
CATEGORY = "Meeeyo/File"
|
||||
|
||||
def IS_CHANGED():
|
||||
return float("NaN")
|
||||
|
||||
def read_excel_row_or_column_diff(self, excel_path, sheet_name, read_mode, indices):
|
||||
try:
|
||||
if not os.path.exists(excel_path):
|
||||
return (f"Error: File does not exist at path: {excel_path}",)
|
||||
|
||||
if not os.access(excel_path, os.R_OK):
|
||||
return (f"Error: No read permission for file at path: {excel_path}",)
|
||||
|
||||
workbook = openpyxl.load_workbook(excel_path, read_only=True, data_only=True)
|
||||
sheet = workbook[sheet_name]
|
||||
|
||||
def count_cells(mode, index):
|
||||
count = 0
|
||||
if mode == "读行":
|
||||
for col in range(1, sheet.max_column + 1):
|
||||
cell_value = sheet.cell(row=index, column=col).value
|
||||
if cell_value is not None:
|
||||
count += 1
|
||||
else:
|
||||
break
|
||||
elif mode == "读列":
|
||||
for row in range(1, sheet.max_row + 1):
|
||||
cell_value = sheet.cell(row=row, column=index).value
|
||||
if cell_value is not None:
|
||||
count += 1
|
||||
else:
|
||||
break
|
||||
return count
|
||||
|
||||
indices = indices.strip()
|
||||
if "," in indices:
|
||||
try:
|
||||
index1, index2 = map(int, indices.split(","))
|
||||
except ValueError:
|
||||
return (f"Error: Invalid indices format. Please use 'number,number' format.",)
|
||||
|
||||
count1 = count_cells(read_mode, index1)
|
||||
count2 = count_cells(read_mode, index2)
|
||||
result = count1 - count2
|
||||
else:
|
||||
try:
|
||||
index = int(indices)
|
||||
except ValueError:
|
||||
return (f"Error: Invalid index format. Please enter a valid number.",)
|
||||
|
||||
result = count_cells(read_mode, index)
|
||||
|
||||
workbook.close()
|
||||
del workbook
|
||||
|
||||
return (result,)
|
||||
|
||||
except Exception as e:
|
||||
return (f"Error: {str(e)}",)
|
||||
+1041
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
#secrets
|
||||
requests>=2.25.1,<3.0.0
|
||||
ntplib
|
||||
openpyxl
|
||||
Reference in New Issue
Block a user