extraer_comb.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. # ===================================================================
  2. # extraer_combos_sap.py
  3. # Función standalone para extraer combinaciones de SAP2000
  4. # ===================================================================
  5. import os
  6. import tkinter as tk
  7. from tkinter.filedialog import asksaveasfilename
  8. from openpyxl import Workbook
  9. from openpyxl.styles import Font, PatternFill, Alignment, Border, Side, NamedStyle
  10. from openpyxl.utils import get_column_letter
  11. # Colores exactos de SAP2000
  12. AZUL_TITULO = "33CCCC" # Azul oscurito título
  13. AZUL_SAP = "CCFFFF" # Azul marino cabecera
  14. # Barra de progreso (la misma que usas en el script principal)
  15. def printProgressBar(iteration, total, prefix='', suffix='', decimals=1, length=50, fill='█'):
  16. percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
  17. filledLength = int(length * iteration // total)
  18. bar = fill * filledLength + '-' * (length - filledLength)
  19. print(f'\r{prefix} |{bar}| {percent}% {suffix}', end="")
  20. if iteration == total:
  21. print()
  22. def extraer_combinaciones_a_excel(SapModel, ruta_excel_origen=None):
  23. """
  24. Extrae todas las combinaciones de SAP2000 y las guarda en Excel
  25. con el formato EXACTO del reporte oficial de SAP2000.
  26. Parámetros:
  27. SapModel: objeto SAP2000 ya conectado
  28. ruta_excel_origen: (opcional) ruta del Excel original para sugerir nombre y carpeta
  29. """
  30. # --- Ventana para guardar ---
  31. root = tk.Tk()
  32. root.withdraw()
  33. root.attributes('-topmost', True)
  34. # Sugerir nombre y carpeta inteligente
  35. if ruta_excel_origen and os.path.exists(ruta_excel_origen):
  36. nombre_base = os.path.splitext(os.path.basename(ruta_excel_origen))[0]
  37. nombre_sugerido = f"{nombre_base}_COMBINACIONES_SAP2000.xlsx"
  38. initialfile = nombre_sugerido
  39. else:
  40. initialfile = "COMBINACIONES_SAP2000.xlsx"
  41. archivo_salida = asksaveasfilename(
  42. initialfile=initialfile,
  43. defaultextension=".xlsx",
  44. filetypes=[("Excel files", "*.xlsx")],
  45. title="Guardar combinaciones (formato SAP2000)"
  46. )
  47. root.destroy()
  48. if not archivo_salida:
  49. print("\nExportación cancelada por el usuario.")
  50. return
  51. # --- Extraer combinaciones ---
  52. ret = SapModel.RespCombo.GetNameList()
  53. num_combos = ret[0]
  54. combo_names = ret[1]
  55. datos = []
  56. for i, combo_name in enumerate(combo_names):
  57. tipo = SapModel.RespCombo.GetTypeOAPI(combo_name)[0]
  58. tipo_texto = "Linear Add" if tipo == 0 else "Envelope" if tipo == 1 else "Other"
  59. casos = SapModel.RespCombo.GetCaseList(combo_name)
  60. nombres_casos = casos[2]
  61. factores = casos[3]
  62. if len(nombres_casos) == 0:
  63. datos.append([combo_name, tipo_texto, "", ""])
  64. else:
  65. for j, caso in enumerate(nombres_casos):
  66. if j == 0:
  67. datos.append([combo_name, tipo_texto, caso, factores[j]])
  68. else:
  69. datos.append(["", "", caso, factores[j]])
  70. printProgressBar(i + 1, num_combos, prefix="Progreso:", suffix="Completado", length=50)
  71. # --- Crear Excel con formato idéntico a SAP2000 ---
  72. wb = Workbook()
  73. ws = wb.active
  74. ws.title = "Combinaciones"
  75. # 1. Título
  76. ws['A1'] = "TABLE: Combination Definitions"
  77. ws['A1'].font = Font(name="Arial Narrow", size=11, bold=True)
  78. ws['A1'].alignment = Alignment(horizontal="center")
  79. ws['A1'].fill = PatternFill(start_color=AZUL_TITULO, end_color=AZUL_TITULO, fill_type="solid")
  80. ws.merge_cells('A1:D1')
  81. # 2. Cabeceras (azul marino SAP2000)
  82. cabeceras = ["ComboName", "ComboType", "CaseName", "ScaleFactor"]
  83. for c, texto in enumerate(cabeceras, 1):
  84. cell = ws.cell(row=2, column=c, value=texto)
  85. cell.font = Font(name="Arial Narrow", bold=True, color="000000", size=10)
  86. cell.fill = PatternFill(start_color=AZUL_SAP, end_color=AZUL_SAP, fill_type="solid")
  87. cell.alignment = Alignment(horizontal="center")
  88. # 3. Tipos de datos (amarillo SAP2000)
  89. tipos = ["Text", "Text", "Text", "Unitless"]
  90. for c, texto in enumerate(tipos, 1):
  91. cell = ws.cell(row=3, column=c, value=texto)
  92. cell.font = Font(name="Arial Narrow", color="000000", size=10)
  93. cell.fill = PatternFill(start_color=AZUL_SAP, end_color=AZUL_SAP, fill_type="solid")
  94. cell.alignment = Alignment(horizontal="center")
  95. # 4. Datos
  96. for r, fila in enumerate(datos, start=4):
  97. for c, valor in enumerate(fila, 1):
  98. cell = ws.cell(row=r, column=c, value=valor)
  99. cell.font = Font(name="Arial Narrow", size=10)
  100. # Aplicar borde fino a todas las celdas
  101. thin_border = Border(left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'), bottom=Side(style='thin'))
  102. for row in ws.iter_rows():
  103. for cell in row:
  104. cell.border = thin_border
  105. # Autoajustar columnas según el contenido (excluyendo la primera fila que está fusionada)
  106. column_widths = {1: 18, 2: 12, 3: 25, 4: 12} # Anchos por defecto
  107. for row in ws.iter_rows(min_row=2, max_row=ws.max_row): # Comienza desde fila 2
  108. for col_idx, cell in enumerate(row, 1):
  109. if cell.value:
  110. cell_len = len(str(cell.value))
  111. if col_idx in column_widths:
  112. column_widths[col_idx] = max(column_widths[col_idx], cell_len)
  113. for col_idx, width in column_widths.items():
  114. ws.column_dimensions[get_column_letter(col_idx)].width = width
  115. # Guardar
  116. wb.save(archivo_salida)
  117. def extraer_flechas(SapModel, ruta_excel_origen=None, var_flechas=None):
  118. """
  119. Función placeholder para extraer flechas.
  120. Actualmente no implementada.
  121. """
  122. # --- Ventana para guardar ---
  123. root = tk.Tk()
  124. root.withdraw()
  125. root.attributes('-topmost', True)
  126. # Sugerir nombre y carpeta inteligente
  127. if ruta_excel_origen and os.path.exists(ruta_excel_origen):
  128. nombre_base = os.path.splitext(os.path.basename(ruta_excel_origen))[0]
  129. nombre_sugerido = f"{nombre_base}_DESPLAZAMIENTOS_SAP2000.xlsx"
  130. initialfile = nombre_sugerido
  131. else:
  132. initialfile = "DESPLAZAMIENTOS_SAP2000.xlsx"
  133. archivo_salida = asksaveasfilename(
  134. initialfile=initialfile,
  135. defaultextension=".xlsx",
  136. filetypes=[("Excel files", "*.xlsx")],
  137. title="Guardar desplazamientos (formato SAP2000)"
  138. )
  139. root.destroy()
  140. if not archivo_salida:
  141. print("\nExportación cancelada por el usuario.")
  142. return
  143. # Obtener desplazamientos en nudos
  144. FieldKeyList = []
  145. GroupName = 'All'
  146. TableVersion = 1
  147. FieldsKeysIncluded = []
  148. NumberRecords = 1
  149. TableData = []
  150. SapModel.SetPresentUnits(9) # Unidades niutons milimetos
  151. ret = SapModel.Results.Setup.DeselectAllCasesAndCombosForOutput()
  152. ret = SapModel.Results.Setup.SetComboSelectedForOutput(var_flechas)
  153. ret = SapModel.DatabaseTables.GetTableforDisplayArray("Joint Displacements", FieldKeyList, GroupName,
  154. TableVersion, FieldsKeysIncluded, NumberRecords, TableData)
  155. datos = []
  156. for i in range(int(len(ret[4])/10)):
  157. 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],
  158. 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]])
  159. # --- Crear Excel con formato idéntico a SAP2000 ---
  160. wb = Workbook()
  161. ws = wb.active
  162. ws.title = "Desplazamientos"
  163. #se ajustan los decimales
  164. flecha_style = NamedStyle(name="flecha_style", number_format="0.00", font=Font(name="Arial Narrow", size=10))
  165. giro_style = NamedStyle(name="giro_style", number_format="0.0000", font=Font(name="Arial Narrow", size=10))
  166. wb.add_named_style(flecha_style)
  167. wb.add_named_style(giro_style)
  168. # 1. Título
  169. ws['A1'] = "TABLE: Joint Displacements"
  170. ws['A1'].font = Font(name="Arial Narrow", size=11, bold=True)
  171. ws['A1'].alignment = Alignment(horizontal="center")
  172. ws['A1'].fill = PatternFill(start_color=AZUL_TITULO, end_color=AZUL_TITULO, fill_type="solid")
  173. ws.merge_cells('A1:J1')
  174. # 2. Cabeceras (azul marino SAP2000)
  175. cabeceras = ret[2]
  176. for c, texto in enumerate(cabeceras, 1):
  177. cell = ws.cell(row=2, column=c, value=texto)
  178. cell.font = Font(name="Arial Narrow", bold=True, color="000000", size=10)
  179. cell.fill = PatternFill(start_color=AZUL_SAP, end_color=AZUL_SAP, fill_type="solid")
  180. cell.alignment = Alignment(horizontal="center")
  181. # 3. Tipos de datos (amarillo SAP2000)
  182. tipos = ["Text", "Text", "Text", "Text", "Length (mm)", "Length (mm)", "Length (mm)", "Angle", "Angle", "Angle"]
  183. for c, texto in enumerate(tipos, 1):
  184. cell = ws.cell(row=3, column=c, value=texto)
  185. cell.font = Font(name="Arial Narrow", color="000000", size=10)
  186. cell.fill = PatternFill(start_color=AZUL_SAP, end_color=AZUL_SAP, fill_type="solid")
  187. cell.alignment = Alignment(horizontal="center")
  188. # 4. Datos
  189. for r, fila in enumerate(datos, start=4):
  190. for c, valor in enumerate(fila, 1):
  191. cell = ws.cell(row=r, column=c, value=valor)
  192. if c > 4:
  193. try:
  194. cell.value = float(valor.replace(',', '.')) # Asegurarse de que es float
  195. except ValueError:
  196. cell.value = valor
  197. cell.font = Font(name="Arial Narrow", size=10)
  198. num_rows = ws.max_row
  199. for row in range(4, num_rows + 1):
  200. for col in ['E', 'F', 'G']: # UX, UY, UZ (flechas)
  201. ws[f'{col}{row}'].style = flecha_style
  202. for col in ['H', 'I', 'J']: # RX, RY, RZ (giros)
  203. ws[f'{col}{row}'].style = giro_style
  204. # Aplicar borde fino a todas las celdas
  205. thin_border = Border(left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'), bottom=Side(style='thin'))
  206. for row in ws.iter_rows():
  207. for cell in row:
  208. cell.border = thin_border
  209. # Autoajustar columnas según el contenido (excluyendo la primera fila que está fusionada)
  210. 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
  211. for row in ws.iter_rows(min_row=2, max_row=ws.max_row): # Comienza desde fila 2
  212. for col_idx, cell in enumerate(row, 1):
  213. if cell.value:
  214. cell_len = len(str(cell.value))
  215. if col_idx in column_widths:
  216. column_widths[col_idx] = max(column_widths[col_idx], cell_len)
  217. for col_idx, width in column_widths.items():
  218. ws.column_dimensions[get_column_letter(col_idx)].width = width
  219. # Guardar
  220. wb.save(archivo_salida)
  221. def extraer_esfuerzos(SapModel, ruta_excel_origen=None, var_esfuerzos=None):
  222. """
  223. Función placeholder para extraer flechas.
  224. Actualmente no implementada.
  225. """
  226. # --- Ventana para guardar ---
  227. root = tk.Tk()
  228. root.withdraw()
  229. root.attributes('-topmost', True)
  230. # Sugerir nombre y carpeta inteligente
  231. if ruta_excel_origen and os.path.exists(ruta_excel_origen):
  232. nombre_base = os.path.splitext(os.path.basename(ruta_excel_origen))[0]
  233. nombre_sugerido = f"{nombre_base}_ESFUERZOS_SAP2000.xlsx"
  234. initialfile = nombre_sugerido
  235. else:
  236. initialfile = "ESFUERZOS_SAP2000.xlsx"
  237. archivo_salida = asksaveasfilename(
  238. initialfile=initialfile,
  239. defaultextension=".xlsx",
  240. filetypes=[("Excel files", "*.xlsx")],
  241. title="Guardar esfuerzos (formato SAP2000)"
  242. )
  243. root.destroy()
  244. if not archivo_salida:
  245. print("\nExportación cancelada por el usuario.")
  246. return
  247. # Obtener desplazamientos en nudos
  248. FieldKeyList = []
  249. GroupName = 'All'
  250. TableVersion = 1
  251. FieldsKeysIncluded = []
  252. NumberRecords = 1
  253. TableData = []
  254. SapModel.SetPresentUnits(6) # Unidades niutons milimetos
  255. ret = SapModel.Results.Setup.DeselectAllCasesAndCombosForOutput()
  256. ret = SapModel.Results.Setup.SetComboSelectedForOutput(var_esfuerzos)
  257. ret = SapModel.DatabaseTables.GetTableforDisplayArray("Element Forces - Frames", FieldKeyList, GroupName,
  258. TableVersion, FieldsKeysIncluded, NumberRecords, TableData)
  259. datos = []
  260. for i in range(int(len(ret[4])/13)):
  261. 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],
  262. 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],
  263. ret[4][i*13+10], ret[4][i*13+11], ret[4][i*13+12]])
  264. # --- Crear Excel con formato idéntico a SAP2000 ---
  265. wb = Workbook()
  266. ws = wb.active
  267. ws.title = "Desplazamientos"
  268. #se ajustan los decimales
  269. flecha_style = NamedStyle(name="flecha_style", number_format="0.00", font=Font(name="Arial Narrow", size=10))
  270. giro_style = NamedStyle(name="giro_style", number_format="0.0000", font=Font(name="Arial Narrow", size=10))
  271. wb.add_named_style(flecha_style)
  272. wb.add_named_style(giro_style)
  273. # 1. Título
  274. ws['A1'] = "TABLE: Joint Displacements"
  275. ws['A1'].font = Font(name="Arial Narrow", size=11, bold=True)
  276. ws['A1'].alignment = Alignment(horizontal="center")
  277. ws['A1'].fill = PatternFill(start_color=AZUL_TITULO, end_color=AZUL_TITULO, fill_type="solid")
  278. ws.merge_cells('A1:M1')
  279. # 2. Cabeceras (azul marino SAP2000)
  280. cabeceras = ret[2]
  281. for c, texto in enumerate(cabeceras, 1):
  282. cell = ws.cell(row=2, column=c, value=texto)
  283. cell.font = Font(name="Arial Narrow", bold=True, color="000000", size=10)
  284. cell.fill = PatternFill(start_color=AZUL_SAP, end_color=AZUL_SAP, fill_type="solid")
  285. cell.alignment = Alignment(horizontal="center")
  286. # 3. Tipos de datos (amarillo SAP2000)
  287. tipos = ["Text", "m", "Text", "Text", "Text", "kN", "kN", "kN", "kNm", "kNm", "kNm", "Text", "Text"]
  288. for c, texto in enumerate(tipos, 1):
  289. cell = ws.cell(row=3, column=c, value=texto)
  290. cell.font = Font(name="Arial Narrow", color="000000", size=10)
  291. cell.fill = PatternFill(start_color=AZUL_SAP, end_color=AZUL_SAP, fill_type="solid")
  292. cell.alignment = Alignment(horizontal="center")
  293. # 4. Datos
  294. for r, fila in enumerate(datos, start=4):
  295. for c, valor in enumerate(fila, 1):
  296. cell = ws.cell(row=r, column=c, value=valor)
  297. if ((c > 5) and (c < 12)) or (c==2):
  298. try:
  299. cell.value = float(valor.replace(',', '.')) # Asegurarse de que es float
  300. except ValueError:
  301. cell.value = valor
  302. cell.font = Font(name="Arial Narrow", size=10)
  303. num_rows = ws.max_row
  304. for row in range(4, num_rows + 1):
  305. for col in ['B','F', 'F', 'G', 'H', 'I', 'J', 'K']: # UX, UY, UZ (flechas)
  306. ws[f'{col}{row}'].style = flecha_style
  307. # Aplicar borde fino a todas las celdas
  308. thin_border = Border(left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'), bottom=Side(style='thin'))
  309. for row in ws.iter_rows():
  310. for cell in row:
  311. cell.border = thin_border
  312. # Autoajustar columnas según el contenido (excluyendo la primera fila que está fusionada)
  313. 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
  314. for row in ws.iter_rows(min_row=2, max_row=ws.max_row): # Comienza desde fila 2
  315. for col_idx, cell in enumerate(row, 1):
  316. if cell.value:
  317. cell_len = len(str(cell.value))
  318. if col_idx in column_widths:
  319. column_widths[col_idx] = max(column_widths[col_idx], cell_len)
  320. for col_idx, width in column_widths.items():
  321. ws.column_dimensions[get_column_letter(col_idx)].width = width
  322. # Guardar
  323. wb.save(archivo_salida)