| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412 |
- # ===================================================================
- # extraer_combos_sap.py
- # Función standalone para extraer combinaciones de SAP2000
- # ===================================================================
- import os
- import tkinter as tk
- from tkinter.filedialog import asksaveasfilename
- from openpyxl import Workbook
- from openpyxl.styles import Font, PatternFill, Alignment, Border, Side, NamedStyle
- from openpyxl.utils import get_column_letter
- # Colores exactos de SAP2000
- AZUL_TITULO = "33CCCC" # Azul oscurito título
- AZUL_SAP = "CCFFFF" # Azul marino cabecera
- # Barra de progreso (la misma que usas en el script principal)
- def printProgressBar(iteration, total, prefix='', suffix='', decimals=1, length=50, fill='█'):
- percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
- filledLength = int(length * iteration // total)
- bar = fill * filledLength + '-' * (length - filledLength)
- print(f'\r{prefix} |{bar}| {percent}% {suffix}', end="")
- if iteration == total:
- print()
- def extraer_combinaciones_a_excel(SapModel, ruta_excel_origen=None):
- """
- Extrae todas las combinaciones de SAP2000 y las guarda en Excel
- con el formato EXACTO del reporte oficial de SAP2000.
-
- Parámetros:
- SapModel: objeto SAP2000 ya conectado
- ruta_excel_origen: (opcional) ruta del Excel original para sugerir nombre y carpeta
- """
- # --- Ventana para guardar ---
- root = tk.Tk()
- root.withdraw()
- root.attributes('-topmost', True)
- # Sugerir nombre y carpeta inteligente
- if ruta_excel_origen and os.path.exists(ruta_excel_origen):
- nombre_base = os.path.splitext(os.path.basename(ruta_excel_origen))[0]
- nombre_sugerido = f"{nombre_base}_COMBINACIONES_SAP2000.xlsx"
- initialfile = nombre_sugerido
- else:
- initialfile = "COMBINACIONES_SAP2000.xlsx"
- archivo_salida = asksaveasfilename(
- initialfile=initialfile,
- defaultextension=".xlsx",
- filetypes=[("Excel files", "*.xlsx")],
- title="Guardar combinaciones (formato SAP2000)"
- )
- root.destroy()
- if not archivo_salida:
- print("\nExportación cancelada por el usuario.")
- return
- # --- Extraer combinaciones ---
- ret = SapModel.RespCombo.GetNameList()
- num_combos = ret[0]
- combo_names = ret[1]
- datos = []
- for i, combo_name in enumerate(combo_names):
- tipo = SapModel.RespCombo.GetTypeOAPI(combo_name)[0]
- tipo_texto = "Linear Add" if tipo == 0 else "Envelope" if tipo == 1 else "Other"
- casos = SapModel.RespCombo.GetCaseList(combo_name)
- nombres_casos = casos[2]
- factores = casos[3]
- if len(nombres_casos) == 0:
- datos.append([combo_name, tipo_texto, "", ""])
- else:
- for j, caso in enumerate(nombres_casos):
- if j == 0:
- datos.append([combo_name, tipo_texto, caso, factores[j]])
- else:
- datos.append(["", "", caso, factores[j]])
- printProgressBar(i + 1, num_combos, prefix="Progreso:", suffix="Completado", length=50)
- # --- Crear Excel con formato idéntico a SAP2000 ---
- wb = Workbook()
- ws = wb.active
- ws.title = "Combinaciones"
- # 1. Título
- ws['A1'] = "TABLE: Combination Definitions"
- ws['A1'].font = Font(name="Arial Narrow", size=11, bold=True)
- ws['A1'].alignment = Alignment(horizontal="center")
- ws['A1'].fill = PatternFill(start_color=AZUL_TITULO, end_color=AZUL_TITULO, fill_type="solid")
- ws.merge_cells('A1:D1')
- # 2. Cabeceras (azul marino SAP2000)
- cabeceras = ["ComboName", "ComboType", "CaseName", "ScaleFactor"]
- for c, texto in enumerate(cabeceras, 1):
- cell = ws.cell(row=2, column=c, value=texto)
- cell.font = Font(name="Arial Narrow", bold=True, color="000000", size=10)
- cell.fill = PatternFill(start_color=AZUL_SAP, end_color=AZUL_SAP, fill_type="solid")
- cell.alignment = Alignment(horizontal="center")
- # 3. Tipos de datos (amarillo SAP2000)
- tipos = ["Text", "Text", "Text", "Unitless"]
- for c, texto in enumerate(tipos, 1):
- cell = ws.cell(row=3, column=c, value=texto)
- cell.font = Font(name="Arial Narrow", color="000000", size=10)
- cell.fill = PatternFill(start_color=AZUL_SAP, end_color=AZUL_SAP, fill_type="solid")
- cell.alignment = Alignment(horizontal="center")
- # 4. Datos
- for r, fila in enumerate(datos, start=4):
- for c, valor in enumerate(fila, 1):
- cell = ws.cell(row=r, column=c, value=valor)
- cell.font = Font(name="Arial Narrow", size=10)
- # Aplicar borde fino a todas las celdas
- thin_border = Border(left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'), bottom=Side(style='thin'))
- for row in ws.iter_rows():
- for cell in row:
- cell.border = thin_border
- # Autoajustar columnas según el contenido (excluyendo la primera fila que está fusionada)
- column_widths = {1: 18, 2: 12, 3: 25, 4: 12} # Anchos por defecto
-
- for row in ws.iter_rows(min_row=2, max_row=ws.max_row): # Comienza desde fila 2
- for col_idx, cell in enumerate(row, 1):
- if cell.value:
- cell_len = len(str(cell.value))
- if col_idx in column_widths:
- column_widths[col_idx] = max(column_widths[col_idx], cell_len)
-
- for col_idx, width in column_widths.items():
- ws.column_dimensions[get_column_letter(col_idx)].width = width
- # Guardar
- wb.save(archivo_salida)
-
- def extraer_flechas(SapModel, ruta_excel_origen=None, var_flechas=None):
- """
- Función placeholder para extraer flechas.
- Actualmente no implementada.
- """
- # --- Ventana para guardar ---
- root = tk.Tk()
- root.withdraw()
- root.attributes('-topmost', True)
- # Sugerir nombre y carpeta inteligente
- if ruta_excel_origen and os.path.exists(ruta_excel_origen):
- nombre_base = os.path.splitext(os.path.basename(ruta_excel_origen))[0]
- nombre_sugerido = f"{nombre_base}_DESPLAZAMIENTOS_SAP2000.xlsx"
- initialfile = nombre_sugerido
- else:
- initialfile = "DESPLAZAMIENTOS_SAP2000.xlsx"
- archivo_salida = asksaveasfilename(
- initialfile=initialfile,
- defaultextension=".xlsx",
- filetypes=[("Excel files", "*.xlsx")],
- title="Guardar desplazamientos (formato SAP2000)"
- )
- root.destroy()
- if not archivo_salida:
- print("\nExportación cancelada por el usuario.")
- return
-
-
- # Obtener desplazamientos en nudos
-
- FieldKeyList = []
- GroupName = 'All'
- TableVersion = 1
- FieldsKeysIncluded = []
- NumberRecords = 1
- TableData = []
- SapModel.SetPresentUnits(9) # Unidades niutons milimetos
- ret = SapModel.Results.Setup.DeselectAllCasesAndCombosForOutput()
- ret = SapModel.Results.Setup.SetComboSelectedForOutput(var_flechas)
- ret = SapModel.DatabaseTables.GetTableforDisplayArray("Joint Displacements", FieldKeyList, GroupName,
- TableVersion, FieldsKeysIncluded, NumberRecords, TableData)
- datos = []
- for i in range(int(len(ret[4])/10)):
- datos.append([ret[4][i*10], ret[4][i*10+1], ret[4][i*10+2], ret[4][i*10+3], ret[4][i*10+4],
- ret[4][i*10+5], ret[4][i*10+6], ret[4][i*10+7], ret[4][i*10+8], ret[4][i*10+9]])
- # --- Crear Excel con formato idéntico a SAP2000 ---
- wb = Workbook()
- ws = wb.active
- ws.title = "Desplazamientos"
- #se ajustan los decimales
- flecha_style = NamedStyle(name="flecha_style", number_format="0.00", font=Font(name="Arial Narrow", size=10))
- giro_style = NamedStyle(name="giro_style", number_format="0.0000", font=Font(name="Arial Narrow", size=10))
- wb.add_named_style(flecha_style)
- wb.add_named_style(giro_style)
- # 1. Título
- ws['A1'] = "TABLE: Joint Displacements"
- ws['A1'].font = Font(name="Arial Narrow", size=11, bold=True)
- ws['A1'].alignment = Alignment(horizontal="center")
- ws['A1'].fill = PatternFill(start_color=AZUL_TITULO, end_color=AZUL_TITULO, fill_type="solid")
- ws.merge_cells('A1:J1')
- # 2. Cabeceras (azul marino SAP2000)
- cabeceras = ret[2]
- for c, texto in enumerate(cabeceras, 1):
- cell = ws.cell(row=2, column=c, value=texto)
- cell.font = Font(name="Arial Narrow", bold=True, color="000000", size=10)
- cell.fill = PatternFill(start_color=AZUL_SAP, end_color=AZUL_SAP, fill_type="solid")
- cell.alignment = Alignment(horizontal="center")
- # 3. Tipos de datos (amarillo SAP2000)
- tipos = ["Text", "Text", "Text", "Text", "Length (mm)", "Length (mm)", "Length (mm)", "Angle", "Angle", "Angle"]
- for c, texto in enumerate(tipos, 1):
- cell = ws.cell(row=3, column=c, value=texto)
- cell.font = Font(name="Arial Narrow", color="000000", size=10)
- cell.fill = PatternFill(start_color=AZUL_SAP, end_color=AZUL_SAP, fill_type="solid")
- cell.alignment = Alignment(horizontal="center")
- # 4. Datos
- for r, fila in enumerate(datos, start=4):
- for c, valor in enumerate(fila, 1):
- cell = ws.cell(row=r, column=c, value=valor)
- if c > 4:
- try:
- cell.value = float(valor.replace(',', '.')) # Asegurarse de que es float
- except ValueError:
- cell.value = valor
- cell.font = Font(name="Arial Narrow", size=10)
-
- num_rows = ws.max_row
- for row in range(4, num_rows + 1):
- for col in ['E', 'F', 'G']: # UX, UY, UZ (flechas)
- ws[f'{col}{row}'].style = flecha_style
- for col in ['H', 'I', 'J']: # RX, RY, RZ (giros)
- ws[f'{col}{row}'].style = giro_style
-
- # Aplicar borde fino a todas las celdas
- thin_border = Border(left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'), bottom=Side(style='thin'))
- for row in ws.iter_rows():
- for cell in row:
- cell.border = thin_border
- # Autoajustar columnas según el contenido (excluyendo la primera fila que está fusionada)
- column_widths = {1: 18, 2: 12, 3: 25, 4: 12, 5: 12, 6: 12, 7: 12, 8: 12, 9: 12, 10: 12} # Anchos por defecto
-
- for row in ws.iter_rows(min_row=2, max_row=ws.max_row): # Comienza desde fila 2
- for col_idx, cell in enumerate(row, 1):
- if cell.value:
- cell_len = len(str(cell.value))
- if col_idx in column_widths:
- column_widths[col_idx] = max(column_widths[col_idx], cell_len)
-
- for col_idx, width in column_widths.items():
- ws.column_dimensions[get_column_letter(col_idx)].width = width
-
- # Guardar
- wb.save(archivo_salida)
- def extraer_esfuerzos(SapModel, ruta_excel_origen=None, var_esfuerzos=None):
- """
- Función placeholder para extraer flechas.
- Actualmente no implementada.
- """
- # --- Ventana para guardar ---
- root = tk.Tk()
- root.withdraw()
- root.attributes('-topmost', True)
- # Sugerir nombre y carpeta inteligente
- if ruta_excel_origen and os.path.exists(ruta_excel_origen):
- nombre_base = os.path.splitext(os.path.basename(ruta_excel_origen))[0]
- nombre_sugerido = f"{nombre_base}_ESFUERZOS_SAP2000.xlsx"
- initialfile = nombre_sugerido
- else:
- initialfile = "ESFUERZOS_SAP2000.xlsx"
- archivo_salida = asksaveasfilename(
- initialfile=initialfile,
- defaultextension=".xlsx",
- filetypes=[("Excel files", "*.xlsx")],
- title="Guardar esfuerzos (formato SAP2000)"
- )
- root.destroy()
- if not archivo_salida:
- print("\nExportación cancelada por el usuario.")
- return
-
-
- # Obtener desplazamientos en nudos
-
- FieldKeyList = []
- GroupName = 'All'
- TableVersion = 1
- FieldsKeysIncluded = []
- NumberRecords = 1
- TableData = []
- SapModel.SetPresentUnits(6) # Unidades niutons milimetos
- ret = SapModel.Results.Setup.DeselectAllCasesAndCombosForOutput()
- ret = SapModel.Results.Setup.SetComboSelectedForOutput(var_esfuerzos)
- ret = SapModel.DatabaseTables.GetTableforDisplayArray("Element Forces - Frames", FieldKeyList, GroupName,
- TableVersion, FieldsKeysIncluded, NumberRecords, TableData)
- datos = []
- for i in range(int(len(ret[4])/13)):
- datos.append([ret[4][i*13], ret[4][i*13+1], ret[4][i*13+2], ret[4][i*13+3], ret[4][i*13+4],
- ret[4][i*13+5], ret[4][i*13+6], ret[4][i*13+7], ret[4][i*13+8], ret[4][i*13+9],
- ret[4][i*13+10], ret[4][i*13+11], ret[4][i*13+12]])
- # --- Crear Excel con formato idéntico a SAP2000 ---
- wb = Workbook()
- ws = wb.active
- ws.title = "Desplazamientos"
- #se ajustan los decimales
- flecha_style = NamedStyle(name="flecha_style", number_format="0.00", font=Font(name="Arial Narrow", size=10))
- giro_style = NamedStyle(name="giro_style", number_format="0.0000", font=Font(name="Arial Narrow", size=10))
- wb.add_named_style(flecha_style)
- wb.add_named_style(giro_style)
- # 1. Título
- ws['A1'] = "TABLE: Joint Displacements"
- ws['A1'].font = Font(name="Arial Narrow", size=11, bold=True)
- ws['A1'].alignment = Alignment(horizontal="center")
- ws['A1'].fill = PatternFill(start_color=AZUL_TITULO, end_color=AZUL_TITULO, fill_type="solid")
- ws.merge_cells('A1:M1')
- # 2. Cabeceras (azul marino SAP2000)
- cabeceras = ret[2]
- for c, texto in enumerate(cabeceras, 1):
- cell = ws.cell(row=2, column=c, value=texto)
- cell.font = Font(name="Arial Narrow", bold=True, color="000000", size=10)
- cell.fill = PatternFill(start_color=AZUL_SAP, end_color=AZUL_SAP, fill_type="solid")
- cell.alignment = Alignment(horizontal="center")
- # 3. Tipos de datos (amarillo SAP2000)
- tipos = ["Text", "m", "Text", "Text", "Text", "kN", "kN", "kN", "kNm", "kNm", "kNm", "Text", "Text"]
- for c, texto in enumerate(tipos, 1):
- cell = ws.cell(row=3, column=c, value=texto)
- cell.font = Font(name="Arial Narrow", color="000000", size=10)
- cell.fill = PatternFill(start_color=AZUL_SAP, end_color=AZUL_SAP, fill_type="solid")
- cell.alignment = Alignment(horizontal="center")
- # 4. Datos
- for r, fila in enumerate(datos, start=4):
- for c, valor in enumerate(fila, 1):
- cell = ws.cell(row=r, column=c, value=valor)
- if ((c > 5) and (c < 12)) or (c==2):
- try:
- cell.value = float(valor.replace(',', '.')) # Asegurarse de que es float
- except ValueError:
- cell.value = valor
- cell.font = Font(name="Arial Narrow", size=10)
-
- num_rows = ws.max_row
- for row in range(4, num_rows + 1):
- for col in ['B','F', 'F', 'G', 'H', 'I', 'J', 'K']: # UX, UY, UZ (flechas)
- ws[f'{col}{row}'].style = flecha_style
-
- # Aplicar borde fino a todas las celdas
- thin_border = Border(left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'), bottom=Side(style='thin'))
- for row in ws.iter_rows():
- for cell in row:
- cell.border = thin_border
- # Autoajustar columnas según el contenido (excluyendo la primera fila que está fusionada)
- column_widths = {1: 18, 2: 12, 3: 25, 4: 12, 5: 12, 6: 12, 7: 12, 8: 12, 9: 12, 10: 12, 11: 12, 12: 12, 13: 12} # Anchos por defecto
-
- for row in ws.iter_rows(min_row=2, max_row=ws.max_row): # Comienza desde fila 2
- for col_idx, cell in enumerate(row, 1):
- if cell.value:
- cell_len = len(str(cell.value))
- if col_idx in column_widths:
- column_widths[col_idx] = max(column_widths[col_idx], cell_len)
-
- for col_idx, width in column_widths.items():
- ws.column_dimensions[get_column_letter(col_idx)].width = width
-
- # Guardar
- wb.save(archivo_salida)
-
|