Cómo analizar formularios PDF mediante una macro de ONLYOFFICE
En el entorno digital acelerado de hoy en día, escritores, editores y creadores de contenido a menudo luchan por obtener información significativa sobre sus documentos. Comprender métricas como la legibilidad, la frecuencia de palabras y el equilibrio estructural puede mejorar significativamente la calidad del documento, pero el análisis manual es lento e inconsistente. En este artículo, te mostraremos cómo crear una macro potente en ONLYOFFICE que analice automáticamente tus documentos y genere informes completos.
Creando la macro para analizar documentos
Dividamos nuestra macro en componentes funcionales y expliquemos cómo funciona cada parte.
Configuración de la función principal
El núcleo de nuestra macro es la función analyzeDocument(), que organiza todo el proceso de análisis:
function analyzeDocument() {
try {
// Get document and all text
var oDocument = Api.GetDocument();
var allText = "";
var paragraphs = oDocument.GetAllParagraphs();
// Check if document is empty
if (paragraphs.length === 0) {
console.log("Warning: Document is empty or no paragraphs found for analysis.");
return;
}
// Collect all text
paragraphs.forEach(function(paragraph) {
allText += paragraph.GetText() + " ";
});
// Perform analyses
var stats = calculateBasicStats(allText, paragraphs);
var advancedStats = calculateAdvancedStats(allText, stats);
var commonWords = findCommonWords(allText, 10);
// Create report
createAndAddReport(oDocument, stats, advancedStats, commonWords);
// Log success
console.log("Success: Document analysis completed. Report added to the end of the document.");
} catch (error) {
console.log("Error: " + error.message);
}
}
Esta función primero recopila todo el texto del documento, luego lo pasa a funciones de análisis especializadas y finalmente crea un informe. El bloque try-catch asegura que la macro maneje los errores de manera adecuada.
Cálculo de estadísticas básicas
La función calculateBasicStats() procesa el texto para extraer métricas fundamentales:
function calculateBasicStats(text, paragraphs) {
// Word count
var words = text.split(/\s+/).filter(function(word) {
return word.length > 0;
});
var wordCount = words.length;
// Sentence count
var sentences = text.split(/[.!?]+/).filter(function(sentence) {
return sentence.trim().length > 0;
});
var sentenceCount = sentences.length;
// Paragraph count
var paragraphCount = paragraphs.length;
// Character count
var charCountWithSpaces = text.length;
var charCountWithoutSpaces = text.replace(/\s+/g, "").length;
// Line count (approximate)
var lineCount = Math.ceil(charCountWithSpaces / 70);
return {
wordCount: wordCount,
sentenceCount: sentenceCount,
paragraphCount: paragraphCount,
charCountWithSpaces: charCountWithSpaces,
charCountWithoutSpaces: charCountWithoutSpaces,
lineCount: lineCount,
words: words,
sentences: sentences
};
}
Esta función divide el texto en palabras y oraciones, cuenta los párrafos y calcula el número de caracteres y líneas.
Realización de análisis avanzados
Para obtener conocimientos más profundos, la función calculateAdvancedStats() calcula métricas más sofisticadas:
function calculateAdvancedStats(text, basicStats) {
// Average sentence length
var avgWordsPerSentence = basicStats.wordCount / Math.max(1, basicStats.sentenceCount);
// Average paragraph length
var avgWordsPerParagraph = basicStats.wordCount / Math.max(1, basicStats.paragraphCount);
// Average word length
var totalWordLength = basicStats.words.reduce(function(sum, word) {
return sum + word.length;
}, 0);
var avgWordLength = totalWordLength / Math.max(1, basicStats.wordCount);
// Readability score (simplified Flesch-Kincaid)
var readabilityScore = 206.835 - 1.015 * avgWordsPerSentence - 84.6 * (totalWordLength / basicStats.wordCount);
// Estimated reading time
var readingTimeMinutes = Math.ceil(basicStats.wordCount / 200);
return {
avgWordsPerSentence: avgWordsPerSentence,
avgWordsPerParagraph: avgWordsPerParagraph,
avgWordLength: avgWordLength,
readabilityScore: readabilityScore,
readingTimeMinutes: readingTimeMinutes
};
}
Esta calcula la longitud promedio de oraciones y párrafos, puntajes de legibilidad y el tiempo estimado de lectura.
Análisis de frecuencia de palabras
La función findCommonWords() identifica las palabras más utilizadas:
function findCommonWords(text, limit) {
// Clean text and convert to lowercase
var cleanText = text.toLowerCase().replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
// Split into words
var words = cleanText.split(/\s+/).filter(function(word) {
return word.length > 3;
});
// Calculate word frequencies
var wordFrequency = {};
words.forEach(function(word) {
wordFrequency[word] = (wordFrequency[word] || 0) + 1;
});
// Filter stop words
var stopWords = ["this", "that", "with", "from", "have", "been"];
stopWords.forEach(function(stopWord) {
delete wordFrequency[stopWord];
});
// Sort by frequency
var sortedWords = Object.keys(wordFrequency).sort(function(a, b) {
return wordFrequency[b] - wordFrequency[a];
});
// Return top N words
return sortedWords.slice(0, limit).map(function(word) {
return { word: word, frequency: wordFrequency[word] };
});
}
function findCommonWords(text, limit) {
// Clean text and convert to lowercase
var cleanText = text.toLowerCase().replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
// Split into words
var words = cleanText.split(/\s+/).filter(function(word) {
return word.length > 3;
});
// Calculate word frequencies
var wordFrequency = {};
words.forEach(function(word) {
wordFrequency[word] = (wordFrequency[word] || 0) + 1;
});
// Filter stop words
var stopWords = ["this", "that", "with", "from", "have", "been"];
stopWords.forEach(function(stopWord) {
delete wordFrequency[stopWord];
});
// Sort by frequency
var sortedWords = Object.keys(wordFrequency).sort(function(a, b) {
return wordFrequency[b] - wordFrequency[a];
});
// Return top N words
return sortedWords.slice(0, limit).map(function(word) {
return { word: word, frequency: wordFrequency[word] };
});
}
Esta función elimina la puntuación, filtra las palabras vacías o de relleno comunes y devuelve las palabras más frecuentes en el documento.
Generación del informe
Finalmente, la función createAndAddReport() compila y da formato a todos los resultados del análisis:
function createAndAddReport(oDocument, basicStats, advancedStats, commonWords) {
// Add new page
var oParagraph = Api.CreateParagraph();
oParagraph.AddPageBreak();
oDocument.AddElement(oDocument.GetElementsCount(), oParagraph);
// Add title
var oHeading = Api.CreateParagraph();
oHeading.AddText("DOCUMENT ANALYSIS REPORT");
oDocument.AddElement(oDocument.GetElementsCount(), oHeading);
// Add basic statistics section
var oSubHeading = Api.CreateParagraph();
oSubHeading.AddText("BASIC STATISTICS");
oDocument.AddElement(oDocument.GetElementsCount(), oSubHeading);
// Add statistics content
// ... (code that adds individual statistics)
// Add advanced analysis section
// ... (code that adds advanced metrics)
// Add word frequency section
// ... (code that adds word frequency list)
// Add footer
var oFootnotePara = Api.CreateParagraph();
oFootnotePara.AddText("This report was generated by OnlyOffice Document Statistics and Analysis Tool on " +
new Date().toLocaleString() + ".");
oDocument.AddElement(oDocument.GetElementsCount(), oFootnotePara);
}
Esta función crea un informe estructurado al final del documento con todos los resultados del análisis.
Código completo de la macro
Aquí tienes el código completo de la macro que puedes copiar y usar:
(function() {
// Main function - starts all operations
function analyzeDocument() {
try {
// Get document and all text
var oDocument = Api.GetDocument();
var allText = "";
var paragraphs = oDocument.GetAllParagraphs();
// Check if document is empty
if (paragraphs.length === 0) {
console.log("Warning: Document is empty or no paragraphs found for analysis.");
return;
}
// Collect all text
paragraphs.forEach(function(paragraph) {
allText += paragraph.GetText() + " ";
});
// Calculate basic statistics
var stats = calculateBasicStats(allText, paragraphs);
// Perform advanced analysis
var advancedStats = calculateAdvancedStats(allText, stats);
// Find most common words
var commonWords = findCommonWords(allText, 10);
// Create and add report to the document
createAndAddReport(oDocument, stats, advancedStats, commonWords);
// Inform user
console.log("Success: Document analysis completed. Report added to the end of the document.");
} catch (error) {
console.log("Error: An error occurred during processing: " + error.message);
}
}
// Calculate basic statistics
function calculateBasicStats(text, paragraphs) {
// Word count
var words = text.split(/\s+/).filter(function(word) {
return word.length > 0;
});
var wordCount = words.length;
// Sentence count
var sentences = text.split(/[.!?]+/).filter(function(sentence) {
return sentence.trim().length > 0;
});
var sentenceCount = sentences.length;
// Paragraph count
var paragraphCount = paragraphs.length;
// Character count (with and without spaces)
var charCountWithSpaces = text.length;
var charCountWithoutSpaces = text.replace(/\s+/g, "").length;
// Line count (approximate)
var lineCount = Math.ceil(charCountWithSpaces / 70); // Approximately 70 characters/line
return {
wordCount: wordCount,
sentenceCount: sentenceCount,
paragraphCount: paragraphCount,
charCountWithSpaces: charCountWithSpaces,
charCountWithoutSpaces: charCountWithoutSpaces,
lineCount: lineCount,
words: words,
sentences: sentences
};
}
// Calculate advanced statistics
function calculateAdvancedStats(text, basicStats) {
// Average sentence length (in words)
var avgWordsPerSentence = basicStats.wordCount / Math.max(1, basicStats.sentenceCount);
// Average paragraph length (in words)
var avgWordsPerParagraph = basicStats.wordCount / Math.max(1, basicStats.paragraphCount);
// Average word length (in characters)
var totalWordLength = basicStats.words.reduce(function(sum, word) {
return sum + word.length;
}, 0);
var avgWordLength = totalWordLength / Math.max(1, basicStats.wordCount);
// Readability score (simplified Flesch-Kincaid)
var readabilityScore = 206.835 - 1.015 * (basicStats.wordCount / Math.max(1, basicStats.sentenceCount)) - 84.6 * (totalWordLength / Math.max(1, basicStats.wordCount));
// Estimated reading time (minutes)
var readingTimeMinutes = Math.ceil(basicStats.wordCount / 200); // Average reading speed 200 words/minute
return {
avgWordsPerSentence: avgWordsPerSentence,
avgWordsPerParagraph: avgWordsPerParagraph,
avgWordLength: avgWordLength,
readabilityScore: readabilityScore,
readingTimeMinutes: readingTimeMinutes
};
}
// Find most common words
function findCommonWords(text, limit) {
// Clean text and convert to lowercase
var cleanText = text.toLowerCase().replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
// Split into words
var words = cleanText.split(/\s+/).filter(function(word) {
return word.length > 3; // Filter out very short words
});
// Calculate word frequencies
var wordFrequency = {};
words.forEach(function(word) {
if (wordFrequency[word]) {
wordFrequency[word]++;
} else {
wordFrequency[word] = 1;
}
});
// Filter stop words (common English words)
var stopWords = ["this", "that", "these", "those", "with", "from", "have", "been", "were", "they", "their", "what", "when", "where", "which", "there", "will", "would", "could", "should", "about", "also"];
stopWords.forEach(function(stopWord) {
if (wordFrequency[stopWord]) {
delete wordFrequency[stopWord];
}
});
// Sort by frequency
var sortedWords = Object.keys(wordFrequency).sort(function(a, b) {
return wordFrequency[b] - wordFrequency[a];
});
// Take top N words
var topWords = sortedWords.slice(0, limit);
// Return results as word-frequency pairs
return topWords.map(function(word) {
return {
word: word,
frequency: wordFrequency[word]
};
});
}
// Create and add report to document
function createAndAddReport(oDocument, basicStats, advancedStats, commonWords) {
// Add new page
var oParagraph = Api.CreateParagraph();
oParagraph.AddPageBreak();
oDocument.AddElement(oDocument.GetElementsCount(), oParagraph);
// Main title - highlighting in capital letters
var oHeading = Api.CreateParagraph();
oHeading.AddText("DOCUMENT ANALYSIS REPORT");
oDocument.AddElement(oDocument.GetElementsCount(), oHeading);
// Subheading - in capital letters
var oSubHeading = Api.CreateParagraph();
oSubHeading.AddText("BASIC STATISTICS");
oDocument.AddElement(oDocument.GetElementsCount(), oSubHeading);
// Add basic statistics
var oStatsPara = Api.CreateParagraph();
oStatsPara.AddText("• Word Count: " + basicStats.wordCount);
oDocument.AddElement(oDocument.GetElementsCount(), oStatsPara);
oStatsPara = Api.CreateParagraph();
oStatsPara.AddText("• Sentence Count: " + basicStats.sentenceCount);
oDocument.AddElement(oDocument.GetElementsCount(), oStatsPara);
oStatsPara = Api.CreateParagraph();
oStatsPara.AddText("• Paragraph Count: " + basicStats.paragraphCount);
oDocument.AddElement(oDocument.GetElementsCount(), oStatsPara);
oStatsPara = Api.CreateParagraph();
oStatsPara.AddText("• Character Count (with spaces): " + basicStats.charCountWithSpaces);
oDocument.AddElement(oDocument.GetElementsCount(), oStatsPara);
oStatsPara = Api.CreateParagraph();
oStatsPara.AddText("• Character Count (without spaces): " + basicStats.charCountWithoutSpaces);
oDocument.AddElement(oDocument.GetElementsCount(), oStatsPara);
oStatsPara = Api.CreateParagraph();
oStatsPara.AddText("• Estimated Line Count: " + basicStats.lineCount);
oDocument.AddElement(oDocument.GetElementsCount(), oStatsPara);
// Advanced analysis title
oSubHeading = Api.CreateParagraph();
oSubHeading.AddText("ADVANCED ANALYSIS");
oDocument.AddElement(oDocument.GetElementsCount(), oSubHeading);
// Add advanced analysis results
oStatsPara = Api.CreateParagraph();
oStatsPara.AddText("• Average Sentence Length: " + advancedStats.avgWordsPerSentence.toFixed(2) + " words");
oDocument.AddElement(oDocument.GetElementsCount(), oStatsPara);
oStatsPara = Api.CreateParagraph();
oStatsPara.AddText("• Average Paragraph Length: " + advancedStats.avgWordsPerParagraph.toFixed(2) + " words");
oDocument.AddElement(oDocument.GetElementsCount(), oStatsPara);
oStatsPara = Api.CreateParagraph();
oStatsPara.AddText("• Average Word Length: " + advancedStats.avgWordLength.toFixed(2) + " characters");
oDocument.AddElement(oDocument.GetElementsCount(), oStatsPara);
oStatsPara = Api.CreateParagraph();
oStatsPara.AddText("• Readability Score: " + advancedStats.readabilityScore.toFixed(2));
oDocument.AddElement(oDocument.GetElementsCount(), oStatsPara);
oStatsPara = Api.CreateParagraph();
oStatsPara.AddText("• Estimated Reading Time: " + advancedStats.readingTimeMinutes + " minutes");
oDocument.AddElement(oDocument.GetElementsCount(), oStatsPara);
// Common words title
oSubHeading = Api.CreateParagraph();
oSubHeading.AddText("MOST FREQUENTLY USED WORDS");
oDocument.AddElement(oDocument.GetElementsCount(), oSubHeading);
// We'll create a simple list instead of a table
if (commonWords.length > 0) {
for (var i = 0; i < commonWords.length; i++) {
var oWordPara = Api.CreateParagraph();
oWordPara.AddText((i + 1) + ". " + commonWords[i].word + " (" + commonWords[i].frequency + " times)");
oDocument.AddElement(oDocument.GetElementsCount(), oWordPara);
}
} else {
var oNoneFoundPara = Api.CreateParagraph();
oNoneFoundPara.AddText("No frequently used words found.");
oDocument.AddElement(oDocument.GetElementsCount(), oNoneFoundPara);
}
// Footer note
var oFootnotePara = Api.CreateParagraph();
oFootnotePara.AddText("This report was generated by OnlyOffice Document Statistics and Analysis Tool on " +
new Date().toLocaleString() + ".");
oDocument.AddElement(oDocument.GetElementsCount(), oFootnotePara);
}
// Run the macro
analyzeDocument();
})();
Para usar esta macro en ONLYOFFICE
- Abre tu documento en ONLYOFFICE
- Ve a la pestaña Vista y selecciona Macros
- Crea una nueva macro y pega el código
- Ejecuta la macro
- Se añadirá un informe de análisis detallado al final del documento
¡Ahora ejecutemos nuestra macro y veamos cómo funciona!
Esta macro es una herramienta valiosa para profesionales que buscan automatizar el análisis de texto y los procesos de documentación en un entorno de oficina moderno. Esperamos que sea una adición útil a tu conjunto de herramientas laborales.
Te animamos a explorar la documentación de la API de ONLYOFFICE para crear tus propias macros personalizadas o mejorar esta. Si tienes ideas para mejoras o sugerencias para nuevas macros, no dudes en contactarnos. Tus comentarios nos ayudan a seguir desarrollando herramientas que hagan más eficiente la creación y edición de documentos.
Sobre el autor
Crea tu cuenta gratuita de ONLYOFFICE
Visualiza, edita y colabora en documentos, hojas, diapositivas, formularios y archivos PDF en línea.