0% encontró este documento útil (0 votos)
5 vistas6 páginas

CODIGOVBA

El documento proporciona un script de Excel que procesa hojas de cálculo, pero sugiere mejoras significativas para optimizar el rendimiento. Se identifican problemas como el recálculo constante al cambiar valores, la copia de filas vacías y patrones ineficientes de manejo de datos. Se recomienda desactivar el cálculo automático durante el proceso y hacer ajustes dinámicos en el rango de datos para reducir el tiempo de procesamiento.

Cargado por

alexforconi
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
5 vistas6 páginas

CODIGOVBA

El documento proporciona un script de Excel que procesa hojas de cálculo, pero sugiere mejoras significativas para optimizar el rendimiento. Se identifican problemas como el recálculo constante al cambiar valores, la copia de filas vacías y patrones ineficientes de manejo de datos. Se recomienda desactivar el cálculo automático durante el proceso y hacer ajustes dinámicos en el rango de datos para reducir el tiempo de procesamiento.

Cargado por

alexforconi
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

{"version":"0.3.0","body":"function main(workbook: ExcelScript.

Workbook) {\n\n //
=========================\n // HOJAS PRINCIPALES\n // =========================\n
const resumen: [Link] = [Link](\"Resumen\");\n const
config: [Link] = [Link](\"Config\");\n\n if (!resumen || !config)
{\n throw new Error(\"Falta la hoja 'Resumen' o 'Config'\");\n }\n\n //
=========================\n // LEER HOJAS A PROCESAR\n //
=========================\n const sheetNames: string[] = config\n .getRange(\"A2:A20\")\n
.getValues()\n .flat()\n .filter((v): v is string => v !== \"\");\n\n if ([Link] === 0) {\n
throw new Error(\"No hay hojas seleccionadas en CONFIG (A2:A20)\");\n }\n\n //
=========================\n // LEER VALORES F4 (1–12)\n //
=========================\n const f4Values: number[] = config\n .getRange(\"C2:C13\")\n
.getValues()\n .flat()\n .filter((v): v is number => typeof v === \"number\" && v >= 1 && v <=
12);\n\n if ([Link] === 0) {\n throw new Error(\"No hay valores F4 válidos en CONFIG
(C2:C13)\");\n }\n\n // =========================\n // LIMPIAR RESUMEN (SIN FILA 1)\n //
=========================\n const usedResumen = [Link]();\n if
(usedResumen && [Link]() > 1) {\n resumen\n .getRangeByIndexes(\n
1,\n 0,\n [Link]() - 1,\n [Link]()\n )\n
.clear([Link]);\n }\n\n let lastRow: number = 1;\n\n //
=========================\n // PROCESAR HOJAS\n // =========================\n
[Link]((sheetName: string) => {\n\n const ws =
[Link](sheetName);\n if (!ws) return;\n\n const cellF4 =
[Link](\"F4\");\n const originalF4 = [Link]();\n\n [Link]((value:
number) => {\n\n [Link](value);\n\n const sourceRange =
[Link](\"A20:Y200\");\n const values = [Link]();\n\n const filtered =
values.filter(row =>\n [Link](cell => cell !== null && cell !== \"\")\n );\n\n if (fi[Link] ===
0) return;\n\n resumen\n .getRangeByIndexes(\n lastRow,\n 0,\n fi[Link],\n
filtered[0].length\n )\n .setValues(filtered);\n\n lastRow += fi[Link];\n });\n\n
[Link](originalF4);\n });\n\n // =========================\n // POST PROCESO\n //
=========================\n applyDateFormat(resumen);\n
applyCalculatedColumns(resumen);\n applyYearMonthColumns(resumen);\n}\n\n//
=======================================================\n// FORMATO FECHA -
COLUMNAS G:H\n//
=======================================================\nfunction
applyDateFormat(sheet: [Link]) {\n\n const used = [Link]();\n if
(!used) return;\n\n const lastRow: number = [Link]();\n if (lastRow <= 1) return;\n\n
const rangeGH = [Link](1, 6, lastRow - 1, 2);\n
[Link](\"dd/mm/yyyy\");\n}\n\n//
=======================================================\n// CÁLCULOS Z:AF
(BLOQUES, SIN TIMEOUT)\n//
=======================================================\nfunction
applyCalculatedColumns(sheet: [Link]) {\n\n const used =
[Link]();\n if (!used) return;\n\n const rowCount: number =
[Link]();\n if (rowCount <= 1) return;\n\n // Fórmulas base en Z2:AF2\n const
formulas: string[] = [\n \"=Q2+R2+U2+V2\",\n \"=Z2/J2\",\n \"=IF(SUM(AC2:AF2)=0,1,0)\",\n
\"=IF((K2<5)*(K2>3),1,0)\",\n \"=IF((K2<3)*(K2>1),1,0)\",\n \"=IF((K2<1)*(K2>0),1,0)\",\n
\"=IF(K2<1,1,0)\"\n ];\n\n const baseRow = [Link](\"Z2:AF2\");\n
[Link]([formulas]);\n\n const totalRows: number = rowCount - 1;\n\n const
formulaRange = [Link](\n 1, // desde fila 2\n 25, // columna Z\n totalRows,\n
7\n );\n\n [Link](baseRow, [Link]);\n\n //
Convertir a valores en bloques\n const blockSize: number = 500;\n\n for (let start = 1; start <=
totalRows; start += blockSize) {\n\n const rows = [Link](blockSize, totalRows - start + 1);\n\n
const chunk = [Link](\n start,\n 25,\n rows,\n 7\n );\n\n const values =
[Link]();\n [Link](values);\n }\n}\n//
=======================================================\n// CÁLCULOS AG:AH →
PEGAR COMO VALORES\n//
=======================================================\nfunction
applyYearMonthColumns(sheet: [Link]) {\n\n const used =
[Link]();\n if (!used) return;\n\n const rowCount: number =
[Link]();\n if (rowCount <= 1) return;\n\n const totalRows: number = rowCount -
1;\n\n // Fórmulas base\n const formulaAG =
'=IF(VALUE(YEAR(G2)&IF(MONTH(G2)<10,\"0\"&MONTH(G2),MONTH(G2)))=A2,1,0)';\n const
formulaAH =
'=IF(VALUE(YEAR(H2)&IF(MONTH(H2)<10,\"0\"&MONTH(H2),MONTH(H2)))=A2,1,0)';\n\n\n // AG
(col 32) y AH (col 33)\n const baseRange = [Link](1, 32, 1, 2);\n
[Link]([[formulaAG, formulaAH]]);\n\n const fullRange =
[Link](\n 1, // fila 2\n 32, // columna AG\n totalRows,\n 2 // AG y AH\n );\n\n
[Link](baseRange, [Link]);\n\n // Convertir a
valores en bloques (seguro para Excel Online)\n const blockSize = 500;\n\n for (let start = 1;
start <= totalRows; start += blockSize) {\n\n const rows = [Link](blockSize, totalRows - start
+ 1);\n\n const chunk = [Link](\n start,\n 32,\n rows,\n 2\n );\n\n const
values = [Link]();\n [Link](values);\n
}\n}\n","description":"","noCodeMetadata":"","parameterInfo":"{\"version\":1,\"originalParameter
Order\":[],\"parameterSchema\":{\"type\":\"object\",\"default\":{},\"x-ms-
visibility\":\"internal\"},\"returnSchema\":{\"type\":\"object\",\"properties\":{}},\"signature\":{\"co
mment\":\"\",\"parameters\":[{\"name\":\"workbook\",\"comment\":\"\"}]}}","apiInfo":"{\"variant\"
:\"synchronous\",\"variantVersion\":2}"}

Tu script está bastante bien estructurado y tiene varias buenas prácticas para evitar timeouts
en Excel Online. Lo que veo es que probablemente estás llegando al límite por recalcular
demasiadas veces al cambiar F4 en cada hoja y copiar rangos completos A20:Y200
repetidamente.

Hay 3 problemas típicos acá:

1. RECÁLCULO CONSTANTE AL CAMBIAR F4

Cada vez que hacés:

[Link](value);

Excel recalcula TODA la hoja.

Si tenés fórmulas pesadas, tablas dinámicas, BUSCARV/XLOOKUP, etc., explota el rendimiento.

2. COPIÁS MUCHAS FILAS VACÍAS

Siempre leés:
A20:Y200

aunque haya 10 filas reales.

Eso multiplica muchísimo el tiempo.

3. COPYFROM + GETVALUES + SETVALUES

Ese patrón genera mucho tráfico entre Excel Script y el workbook.

TE RECOMIENDO ESTA MEJORA CLAVE

DESACTIVAR CÁLCULO AUTOMÁTICO DURANTE EL PROCESO

Esto suele acelerar entre 5x y 20x.

Agregá al principio:

const app = [Link]();


const originalMode = [Link]();

[Link]([Link]);

Y al final:

[Link]([Link]);
[Link](originalMode);

OTRA MEJORA IMPORTANTE

En vez de:

const sourceRange = [Link]("A20:Y200");

hacé algo dinámico:

const used = [Link]();


if (!used) return;

const lastUsedRow = [Link]();

if (lastUsedRow < 20) return;

const sourceRange = [Link](`A20:Y${lastUsedRow}`);

Eso puede reducir muchísimo el procesamiento.

TAMBIÉN TE CONVIENE ESTO

EVITAR .some() EN CADA CELDA


Esto:

const filtered = values.filter(row =>


[Link](cell => cell !== null && cell !== "")
);

es bastante costoso.

Mejor:

const filtered = values.filter(row =>


[Link]("").trim() !== ""
);

Más rápido.

EL PROBLEMA MÁS PELIGROSO

Esto:

[Link](baseRow, [Link]);

sobre miles de filas puede romper Excel Online.

MUCHO más estable:

const formulasMatrix = Array(totalRows).fill(formulas);

[Link](formulasMatrix);

Lo mismo para AG:AH.

EL CAMBIO MÁS IMPORTANTE DE TODOS

Tu script:

1. cambia F4

2. espera recálculo

3. copia datos

4. vuelve a cambiar F4

5. recalcula otra vez

Eso puede generar cientos de recálculos completos.

Si podés mover la lógica de F4 a fórmulas internas o hacer un cálculo por lote, el rendimiento
cambia radicalmente.

VERSION MEJORADA DEL BLOQUE PRINCIPAL


Este reemplazo solo ya mejora muchísimo:

const app = [Link]();


const originalMode = [Link]();

[Link]([Link]);

try {

[Link]((sheetName: string) => {

const ws = [Link](sheetName);
if (!ws) return;

const cellF4 = [Link]("F4");


const originalF4 = [Link]();

const used = [Link]();


if (!used) return;

const lastUsedRow = [Link]();

if (lastUsedRow < 20) return;

[Link]((value: number) => {

[Link](value);

[Link]([Link]);

const sourceRange = [Link](`A20:Y${lastUsedRow}`);

const values = [Link]();

const filtered = values.filter(row =>


[Link]("").trim() !== ""
);

if (fi[Link] === 0) return;

resumen
.getRangeByIndexes(
lastRow,
0,
fi[Link],
filtered[0].length
)
.setValues(filtered);
lastRow += fi[Link];
});

[Link](originalF4);
});

} finally {

[Link]([Link]);

[Link](originalMode);
}

SI TODAVÍA FALLA

Entonces el problema seguramente está en:

 fórmulas volátiles

 INDIRECT

 OFFSET

 tablas dinámicas

 BUSCARV masivos

 fórmulas matriciales

 demasiados formatos condicionales

Ahí ya conviene rediseñar el Excel, no solo el script.

Y sinceramente: cuando Excel Online empieza a borrar tablas dinámicas o “romper” hojas
como comentaste antes, normalmente es porque el archivo ya está al límite de complejidad.

También podría gustarte