Объект JavaScript VBA не поддерживает это свойство или метод
Я пытаюсь получить функцию статистики текста из https://github.com/cgiffard/TextStatistics.js/blob/master/index.js
Работа в Excel
Я сократил код JavaScript, чтобы сократить конкатенации
Function Text_Statistics1(textString As String)
Dim code As String
code = "function text_stats(teststringtoprocess){(function(e){function t(e){var t=['li','p','h1','h2','h3','h4','h5','h6','dd'];t.forEach(function(t){e=e.replace('</'+t+'>','.')});e=e.replace(/<[^>]+>/g,'').replace(/[,:;()\-]/,' ').replace(/[\.!?]/,'.').replace(/^\s+/,'').replace(/[ ]*(\n|\r\n|\r)[ ]*/,' ').replace(/([\.])[\. ]+/,'.').replace(/[ ]*([\.])/,'. ').replace(/\s+/,' ').replace(/\s+$/,'');e+='.';return e}function r(e){return new n(e)}var n=function(n){this.text=n?t(n):this.text};n.prototype.fleschKincaidReadingEase=function(e){e=e?t(e):this.text;return Math.round((206.835-1.015*this.averageWordsPerSentence(e)-84.6*this.averageSyllablesPerWord(e))*10)/10};n.prototype.fleschKincaidGradeLevel=function(e){e=e?t(e):this.text;return Math.round((.39*this.averageWordsPerSentence(e)+11.8*this.averageSyllablesPerWord(e)-15.59)*10)/10};n.prototype.gunningFogScore=function(e){e=e?t(e):this.text;"
code = code + "return Math.round((this.averageWordsPerSentence(e)+this.percentageWordsWithThreeSyllables(e,false))*.4*10)/10};n.prototype.colemanLiauIndex=function(e){e=e?t(e):this.text;return Math.round((5.89*(this.letterCount(e)/this.wordCount(e))-.3*(this.sentenceCount(e)/this.wordCount(e))-15.8)*10)/10};n.prototype.smogIndex=function(e){e=e?t(e):this.text;return Math.round(1.043*Math.sqrt(this.wordsWithThreeSyllables(e)*(30/this.sentenceCount(e))+3.1291)*10)/10};n.prototype.automatedReadabilityIndex=function(e){e=e?t(e):this.text;"
code = code + "return Math.round((4.71*(this.letterCount(e)/this.wordCount(e))+.5*(this.wordCount(e)/this.sentenceCount(e))-21.43)*10)/10};n.prototype.textLength=function(e){e=e?t(e):this.text;return e.length};n.prototype.letterCount=function(e){e=e?t(e):this.text;e=e.replace(/[^a-z]+/ig,'');return e.length};n.prototype.sentenceCount=function(e){e=e?t(e):this.text;return e.replace(/[^\.!?]/g,'').length||1};n.prototype.wordCount=function(e){e=e?t(e):this.text;return e.split(/[^a-z0-9]+/i).length||1};n.prototype.averageWordsPerSentence=function(e){e=e?t(e):this.text;"
code = code + "return this.wordCount(e)/this.sentenceCount(e)};n.prototype.averageSyllablesPerWord=function(e){e=e?t(e):this.text;var n=0,r=this.wordCount(e),i=this;e.split(/\s+/).forEach(function(e){n+=i.syllableCount(e)});return(n||1)/(r||1)};n.prototype.wordsWithThreeSyllables=function(e,n){e=e?t(e):this.text;var r=0,i=this;n=n===false?false:true;e.split(/\s+/).forEach(function(e){if(!e.match(/^[A-Z]/)||n){if(i.syllableCount(e)>2)r++}});return r};n.prototype.percentageWordsWithThreeSyllables=function(e,n){e=e?t(e):this.text;return this.wordsWithThreeSyllables(e,n)/this.wordCount(e)*100};n.prototype.syllableCount=function(e){var t=0,n=0,r=0;e=e.toLowerCase().replace(/[^a-z]/g,'');var i={simile:3,forever:3,shoreline:2};if(i.hasOwnProperty(e))return i[e];var s=[/cial/,/tia/,/cius/,/cious/,/giu/,/ion/,/iou/,/sia$/,/[^aeiuoyt]{2,}ed$/,/.ely$/,/[cg]h?e[rsd]?$/,/rved?$/,/[aeiouy][dt]es?$/,/[aeiouy][^aeiouydt]e[rsd]?$/,/^[dr]e[aeiou][^aeiou]+$/,/[aeiouy]rse$/];"
code = code + "var o=[/ia/,/riet/,/dien/,/iu/,/io/,/ii/,/[aeiouym]bl$/,/[aeiou]{3}/,/^mc/,/ism$/,/([^aeiouy])\1l$/,/[^l]lien/,/^coa[dglx]./,/[^gq]ua[^auieo]/,/dnt$/,/uity$/,/ie(r|st)$/];var u=[/^un/,/^fore/,/ly$/,/less$/,/ful$/,/ers?$/,/ings?$/];u.forEach(function(t){if(e.match(t)){e=e.replace(t,'');n++}});r=e.split(/[^aeiouy]+/ig).filter(function(e){return!!e.replace(/\s+/ig,'').length}).length;t=r+n;s.forEach(function(n){if(e.match(n))t--});o.forEach(function(n){if(e.match(n))t++});return t||1};typeof module!='undefined'&&module.exports?module.exports=r:typeof define!='undefined'?define('textstatistics',[],function(){return r}):e.textstatistics=r})(this);"
'code = code + " return textstatistics(s).fleschKincaidReadingEase();" & _
'"return stat.fleschKincaidReadingEase();" & _
code = code + "return textstatistics(teststringtoprocess).fleschKincaidReadingEase();}"
'code = code + "return textstatistics(teststringtoprocess);}"
Dim o As New ScriptControl
o.Language = "JScript"
With o
.AddCode code
Text_Statistics1 = .Run("text_stats", textString)
End With
End Function
Я получаю объект не поддерживает это свойство или метод - я думаю, это связано с созданием текстовой статистики.
Нужно ли конвертировать JavaScript как набор функций?
ОБНОВЛЕНИЕ: немного другой подход с использованием eval
Function Text_Stat(textString As String, textstat As String)
Dim code As String
code = "(function(e){function t(e){var t=['li','p','h1','h2','h3','h4','h5','h6','dd'];t.forEach(function(t){e=e.replace('</'+t+'>','.')});e=e.replace(/<[^>]+>/g,'').replace(/[,:;()\-]/,' ').replace(/[\.!?]/,'.').replace(/^\s+/,'').replace(/[ ]*(\n|\r\n|\r)[ ]*/,' ').replace(/([\.])[\. ]+/,'.').replace(/[ ]*([\.])/,'. ').replace(/\s+/,' ').replace(/\s+$/,'');e+='.';return e}function r(e){return new n(e)}var n=function(n){this.text=n?t(n):this.text};n.prototype.fleschKincaidReadingEase=function(e){e=e?t(e):this.text;return Math.round((206.835-1.015*this.averageWordsPerSentence(e)-84.6*this.averageSyllablesPerWord(e))*10)/10};n.prototype.fleschKincaidGradeLevel=function(e){e=e?t(e):this.text;" & _
"return Math.round((.39*this.averageWordsPerSentence(e)+11.8*this.averageSyllablesPerWord(e)-15.59)*10)/10};n.prototype.gunningFogScore=function(e){e=e?t(e):this.text;return Math.round((this.averageWordsPerSentence(e)+this.percentageWordsWithThreeSyllables(e,false))*.4*10)/10};n.prototype.colemanLiauIndex=function(e){e=e?t(e):this.text;return Math.round((5.89*(this.letterCount(e)/this.wordCount(e))-.3*(this.sentenceCount(e)/this.wordCount(e))-15.8)*10)/10};n.prototype.smogIndex=function(e){e=e?t(e):this.text;return Math.round(1.043*Math.sqrt(this.wordsWithThreeSyllables(e)*(30/this.sentenceCount(e))+3.1291)*10)/10};n.prototype.automatedReadabilityIndex=function(e){e=e?t(e):this.text;" & _
"return Math.round((4.71*(this.letterCount(e)/this.wordCount(e))+.5*(this.wordCount(e)/this.sentenceCount(e))-21.43)*10)/10};n.prototype.textLength=function(e){e=e?t(e):this.text;return e.length};n.prototype.letterCount=function(e){e=e?t(e):this.text;e=e.replace(/[^a-z]+/ig,'');return e.length};n.prototype.sentenceCount=function(e){e=e?t(e):this.text;return e.replace(/[^\.!?]/g,'').length||1};n.prototype.wordCount=function(e){e=e?t(e):this.text;return e.split(/[^a-z0-9]+/i).length||1};n.prototype.averageWordsPerSentence=function(e){e=e?t(e):this.text;return this.wordCount(e)/this.sentenceCount(e)};n.prototype.averageSyllablesPerWord=function(e){e=e?t(e):this.text;var n=0,r=this.wordCount(e),i=this;e.split(/\s+/).forEach(function(e){n+=i.syllableCount(e)});return(n||1)/(r||1)};n.prototype.wordsWithThreeSyllables=function(e,n){e=e?t(e):this.text;" & _
"var r=0,i=this;n=n===false?false:true;e.split(/\s+/).forEach(function(e){if(!e.match(/^[A-Z]/)||n){if(i.syllableCount(e)>2)r++}});return r};n.prototype.percentageWordsWithThreeSyllables=function(e,n){e=e?t(e):this.text;" & _
"return this.wordsWithThreeSyllables(e,n)/this.wordCount(e)*100};n.prototype.syllableCount=function(e){var t=0,n=0,r=0;e=e.toLowerCase().replace(/[^a-z]/g,'');var i={simile:3,forever:3,shoreline:2};if(i.hasOwnProperty(e))return i[e];var s=[/cial/,/tia/,/cius/,/cious/,/giu/,/ion/,/iou/,/sia$/,/[^aeiuoyt]{2,}ed$/,/.ely$/,/[cg]h?e[rsd]?$/,/rved?$/,/[aeiouy][dt]es?$/,/[aeiouy][^aeiouydt]e[rsd]?$/,/^[dr]e[aeiou][^aeiou]+$/,/[aeiouy]rse$/];var o=[/ia/,/riet/,/dien/,/iu/,/io/,/ii/,/[aeiouym]bl$/,/[aeiou]{3}/,/^mc/,/ism$/,/([^aeiouy])\1l$/,/[^l]lien/,/^coa[dglx]./,/[^gq]ua[^auieo]/,/dnt$/,/uity$/,/ie(r|st)$/];" & _
"var u=[/^un/,/^fore/,/ly$/,/less$/,/ful$/,/ers?$/,/ings?$/];u.forEach(function(t){if(e.match(t)){e=e.replace(t,'');n++}});r=e.split(/[^aeiouy]+/ig).filter(function(e){return!!e.replace(/\s+/ig,'').length}).length;t=r+n;s.forEach(function(n){if(e.match(n))t--});o.forEach(function(n){if(e.match(n))t++});return t||1};typeof module!='undefined'&&module.exports?module.exports=r:typeof define!='undefined'?define('textstatistics',[],function(){return r}):e.textstatistics=r})(this);" & _
"var stat = new textstatistics('Your text here');alert(stat.sentenceCount('This. dfgdfg. is. a. long. sentence.'));"
Dim o As New ScriptControl
o.Language = "JScript"
With o
.AllowUI = True
.AddCode code
.Eval "stat.sentenceCount('This. dfgdfg. is. a. long. sentence.')"
'result = .Eval(code)
'Debug.Print .Eval("'Hello World'.substring(1, 4);")
'result = .Eval(result)
'Text_Stat = .Run(result)
End With
End Function
JSFiddle показывает, что он работает здесь http://jsfiddle.net/hwr26dkf/
ОБНОВЛЕНИЕ: 10.10.2014 Окончательная рабочая версия VBA благодаря Майклу Петчу
Function Text_Statistics(statType As Integer, textString As String)
Dim wc, sc As Integer
Dim s1, s2, code As String
Dim oTextStats As Object
Dim o As New ScriptControl
code = "function cleanText(e){var t=['li','p','h1','h2','h3','h4','h5','h6','dd'];t.forEach(function(t){e=e.replace('</'+t+'>','.')});e=e.replace(/<[^>]+>/g,'').replace(/[,:;()\-]/,' ').replace(/[\.!?]/,'.').replace(/^\s+/,'').replace(/[ ]*(\n|\r\n|\r)[ ]*/,' ').replace(/([\.])[\. ]+/,'.').replace(/[ ]*([\.])/,'. ').replace(/\s+/,' ').replace(/\s+$/,'');e+='.';return e}function textStatistics(e){return new TextStatistics(e)}if(!Array.prototype.forEach){Array.prototype.forEach=function(e){var t=this.length;" & _
"if(typeof e!='function')throw new TypeError;var n=arguments[1];for(var r=0;r<t;r++){if(r in this)e.call(n,this[r],r,this)}}}if(!Array.prototype.filter){Array.prototype.filter=function(e){'use strict';if(this===void 0||this===null){throw new TypeError}var t=Object(this);var n=t.length>>>0;if(typeof e!=='function'){throw new TypeError}var r=[];var i=arguments.length>=2?arguments[1]:void 0;for(var s=0;s<n;s++){if(s in t){var o=t[s];if(e.call(i,o,s,t)){r.push(o)}}}return r}}var TextStatistics=function(t){this.text=t?cleanText(t):this.text};TextStatistics.prototype.fleschKincaidReadingEase=function(e){e=e?cleanText(e):this.text;return Math.round((206.835-1.015*this.averageWordsPerSentence(e)-84.6*this.averageSyllablesPerWord(e))*10)/10};TextStatistics.prototype.fleschKincaidGradeLevel=function(e){e=e?cleanText(e):this.text;" & _
"return Math.round((.39*this.averageWordsPerSentence(e)+11.8*this.averageSyllablesPerWord(e)-15.59)*10)/10};TextStatistics.prototype.gunningFogScore=function(e){e=e?cleanText(e):this.text;return Math.round((this.averageWordsPerSentence(e)+this.percentageWordsWithThreeSyllables(e,false))*.4*10)/10};TextStatistics.prototype.colemanLiauIndex=function(e){e=e?cleanText(e):this.text;return Math.round((5.89*(this.letterCount(e)/this.wordCount(e))-.3*(this.sentenceCount(e)/this.wordCount(e))-15.8)*10)/10};" & _
"TextStatistics.prototype.smogIndex=function(e){e=e?cleanText(e):this.text;return Math.round(1.043*Math.sqrt(this.wordsWithThreeSyllables(e)*(30/this.sentenceCount(e))+3.1291)*10)/10};TextStatistics.prototype.automatedReadabilityIndex=function(e){e=e?cleanText(e):this.text;return Math.round((4.71*(this.letterCount(e)/this.wordCount(e))+.5*(this.wordCount(e)/this.sentenceCount(e))-21.43)*10)/10};TextStatistics.prototype.textLength=function(e){e=e?cleanText(e):this.text;return e.length};TextStatistics.prototype.letterCount=function(e){e=e?cleanText(e):this.text;e=e.replace(/[^a-z]+/ig,'');return e.length};TextStatistics.prototype.sentenceCount=function(e){e=e?cleanText(e):this.text;" & _
"return e.replace(/[^\.!?]/g,'').length||1};TextStatistics.prototype.wordCount=function(e){e=e?cleanText(e):this.text;return e.split(/[^a-z0-9]+/i).length||1};TextStatistics.prototype.averageWordsPerSentence=function(e){e=e?cleanText(e):this.text;return this.wordCount(e)/this.sentenceCount(e)};TextStatistics.prototype.averageSyllablesPerWord=function(e){e=e?cleanText(e):this.text;" & _
"var t=0,n=this.wordCount(e),r=this;e.split(/\s+/).forEach(function(e){t+=r.syllableCount(e)});return(t||1)/(n||1)};TextStatistics.prototype.wordsWithThreeSyllables=function(e,t){e=e?cleanText(e):this.text;var n=0,r=this;t=t===false?false:true;e.split(/\s+/).forEach(function(e){if(!e.match(/^[A-Z]/)||t){if(r.syllableCount(e)>2)n++}});return n};TextStatistics.prototype.percentageWordsWithThreeSyllables=function(e,t){e=e?cleanText(e):this.text;return this.wordsWithThreeSyllables(e,t)/this.wordCount(e)*100};" & _
"TextStatistics.prototype.syllableCount=function(e){var t=0,n=0,r=0;e=e.toLowerCase().replace(/[^a-z]/g,'');var i={simile:3,forever:3,shoreline:2};if(i.hasOwnProperty(e))return i[e];var s=[/cial/,/tia/,/cius/,/cious/,/giu/,/ion/,/iou/,/sia$/,/[^aeiuoyt]{2,}ed$/,/.ely$/,/[cg]h?e[rsd]?$/,/rved?$/,/[aeiouy][dt]es?$/,/[aeiouy][^aeiouydt]e[rsd]?$/,/^[dr]e[aeiou][^aeiou]+$/,/[aeiouy]rse$/];var o=[/ia/,/riet/,/dien/,/iu/,/io/,/ii/,/[aeiouym]bl$/,/[aeiou]{3}/,/^mc/,/ism$/,/([^aeiouy])\1l$/,/[^l]lien/,/^coa[dglx]./,/[^gq]ua[^auieo]/,/dnt$/,/uity$/,/ie(r|st)$/];" & _
"var u=[/^un/,/^fore/,/ly$/,/less$/,/ful$/,/ers?$/,/ings?$/];u.forEach(function(t){if(e.match(t)){e=e.replace(t,'');n++}});r=e.split(/[^aeiouy]+/ig).filter(function(e){return!!e.replace(/\s+/ig,'').length}).length;t=r+n;s.forEach(function(n){if(e.match(n))t--});o.forEach(function(n){if(e.match(n))t++});return t||1}"
With o
.Language = "JScript"
.AddCode code
' Create a TextStatistics object initially with no text.
' textStatistics is a function that creates TextStatistics objects
Set oTextStats = .Eval("textStatistics()")
' Now simply call TextStatistics methods directly
wc = oTextStats.averageWordsPerSentence(textString)
sc = oTextStats.syllableCount(textString)
' Alternatively you can create a TextStatistics object with the text
' and call the methods with a blank string to return the values
' for the string passed in the constructor
'Set oTextStats = .Eval("textStatistics('" + textString + "')")
'wc = oTextStats.wordCount("")
'sc = oTextStats.sentenceCount("")
Select Case statType
Case 1
Text_Statistics = oTextStats.wordCount(textString)
Case 2
Text_Statistics = oTextStats.sentenceCount(textString)
Case 3
Text_Statistics = oTextStats.fleschKincaidReadingEase(textString)
Case 4
Text_Statistics = oTextStats.fleschKincaidGradeLevel(textString)
Case 5
Text_Statistics = oTextStats.gunningFogScore(textString)
Case 6
Text_Statistics = oTextStats.colemanLiauIndex(textString)
Case 7
Text_Statistics = oTextStats.smogIndex(textString)
Case 8
Text_Statistics = oTextStats.automatedReadabilityIndex(textString)
Case 9
Text_Statistics = oTextStats.textLength(textString)
Case 10
Text_Statistics = oTextStats.letterCount(textString)
Case 11
Text_Statistics = oTextStats.averageWordsPerSentence(textString)
Case 12
Text_Statistics = oTextStats.averageSyllablesPerWord(textString)
End Select
End With
End Function
1 ответ
Сегодня я потратил некоторое время на изучение Javascript, а затем пытался выяснить, что происходит с вашим TextStatistics
класс при запуске в Microsoft ScriptControl
объект. Вместо того, чтобы начинать с искаженного кода в VBA, я вернулся к коду в github, на который ссылается OP. Первое, что я обнаружил, - это то, что ScriptControl будет анализировать и выполнять анонимную глобальную функцию, однако, как только этот код добавляется ScriptControl, он, похоже, теряет объект TextStatistics. Поэтому первое, что я сделал, это просто удалил анонимную глобальную функцию, удалив ее сверху:
(function(glob) {
и удалив эти строки внизу:
(typeof module != "undefined" && module.exports) ? (module.exports = textStatistics) : (typeof define != "undefined" ? (define("textstatistics", [], function() { return textStatistics; })) : (glob.textstatistics = textStatistics));
})(this);
Как только я удалил это как источник проблем, я обнаружил, что могу создавать новые экземпляры TextStatistics
но я не мог назначить им текст должным образом. Ни как параметр, использующий new
или с помощью вызова метода, как sentenceCount()
, Это меня озадачило. С момента создания экземпляра TextStatistics
не может быть сделано правильно, я решил пересмотреть конструктор. Это просто, но это называется cleanText
, Одна вещь, которая выделялась на меня, была forEach
, По догадкам я немного покопался о Javascript / ScriptControl и затем forEach. Я узнал, что ScriptControl использует ECMAScript, а не Javascript. Как только я понял это, я нашел ссылку с этой информацией, которая включает в себя этот комментарий: о forEach
метод:
Этот метод является расширением JavaScript к стандарту ECMA-262; как таковой он может не присутствовать в других реализациях стандарта. Чтобы это работало, вам нужно добавить следующий код вверху вашего скрипта:
И этот код:
if (!Array.prototype.forEach) {
Array.prototype.forEach = function (fun /*, thisp*/ ) {
var len = this.length;
if (typeof fun != 'function') throw new TypeError();
var thisp = arguments[1];
for (var i = 0; i < len; i++) {
if (i in this) fun.call(thisp, this[i], i, this);
}
};
}
После предоставления моего первоначального ответа ОП обнаружил, что функции, включающие слоги, не работают. В более поздней спецификации ECMA появилась другая функция, которая ScriptControl
не поддерживал Это был полифилл filter
функция на массивах. Согласно этой документации Mozilla:
фильтр был добавлен к стандарту ECMA-262 в 5-м издании; как таковой он может присутствовать не во всех реализациях стандарта. Вы можете обойти это, вставив следующий код в начало ваших сценариев, позволяя использовать фильтр в реализациях ECMA-262, которые изначально не поддерживают его.
Предоставленный код, который соответствует спецификации:
if (!Array.prototype.filter) {
Array.prototype.filter = function(fun/*, thisArg*/) {
'use strict';
if (this === void 0 || this === null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== 'function') {
throw new TypeError();
}
var res = [];
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (var i = 0; i < len; i++) {
if (i in t) {
var val = t[i];
// NOTE: Technically this should Object.defineProperty at
// the next index, as push can be affected by
// properties on Object.prototype and Array.prototype.
// But that method's new, and collisions should be
// rare, so use the more-compatible alternative.
if (fun.call(thisArg, val, i, t)) {
res.push(val);
}
}
}
return res;
};
}
Это было так просто? Было ли это причиной этих проблем? Да, это было Я добавил этот код в начало скрипта, и VBA и ScriptControl были довольны. Поэтому, прежде чем минимизировать и преобразовать все "
в '
код Javascript в целом выглядит следующим образом:
if (!Array.prototype.forEach) {
Array.prototype.forEach = function (fun /*, thisp*/ ) {
var len = this.length;
if (typeof fun != 'function') throw new TypeError();
var thisp = arguments[1];
for (var i = 0; i < len; i++) {
if (i in this) fun.call(thisp, this[i], i, this);
}
};
}
if (!Array.prototype.filter) {
Array.prototype.filter = function(fun/*, thisArg*/) {
'use strict';
if (this === void 0 || this === null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== 'function') {
throw new TypeError();
}
var res = [];
var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (var i = 0; i < len; i++) {
if (i in t) {
var val = t[i];
// NOTE: Technically this should Object.defineProperty at
// the next index, as push can be affected by
// properties on Object.prototype and Array.prototype.
// But that method's new, and collisions should be
// rare, so use the more-compatible alternative.
if (fun.call(thisArg, val, i, t)) {
res.push(val);
}
}
}
return res;
};
}
function cleanText(text) {
// all these tags should be preceeded by a full stop.
var fullStopTags = ['li', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'dd'];
fullStopTags.forEach(function (tag) {
text = text.replace('</' + tag + '>', '.');
});
text = text.replace(/<[^>]+>/g, '') // Strip tags
.replace(/[,:;()\-]/, ' ') // Replace commans, hyphens etc (count them as spaces)
.replace(/[\.!?]/, '.') // Unify terminators
.replace(/^\s+/, '') // Strip leading whitespace
.replace(/[ ]*(\n|\r\n|\r)[ ]*/, ' ') // Replace new lines with spaces
.replace(/([\.])[\. ]+/, '.') // Check for duplicated terminators
.replace(/[ ]*([\.])/, '. ') // Pad sentence terminators
.replace(/\s+/, ' ') // Remove multiple spaces
.replace(/\s+$/, ''); // Strip trailing whitespace
text += '.'; // Add final terminator, just in case it's missing.
return text;
}
var TextStatistics = function TextStatistics(text) {
this.text = text ? cleanText(text) : this.text;
};
TextStatistics.prototype.fleschKincaidReadingEase = function (text) {
text = text ? cleanText(text) : this.text;
return Math.round((206.835 - (1.015 * this.averageWordsPerSentence(text)) - (84.6 * this.averageSyllablesPerWord(text))) * 10) / 10;
};
TextStatistics.prototype.fleschKincaidGradeLevel = function (text) {
text = text ? cleanText(text) : this.text;
return Math.round(((0.39 * this.averageWordsPerSentence(text)) + (11.8 * this.averageSyllablesPerWord(text)) - 15.59) * 10) / 10;
};
TextStatistics.prototype.gunningFogScore = function (text) {
text = text ? cleanText(text) : this.text;
return Math.round(((this.averageWordsPerSentence(text) + this.percentageWordsWithThreeSyllables(text, false)) * 0.4) * 10) / 10;
};
TextStatistics.prototype.colemanLiauIndex = function (text) {
text = text ? cleanText(text) : this.text;
return Math.round(((5.89 * (this.letterCount(text) / this.wordCount(text))) - (0.3 * (this.sentenceCount(text) / this.wordCount(text))) - 15.8) * 10) / 10;
};
TextStatistics.prototype.smogIndex = function (text) {
text = text ? cleanText(text) : this.text;
return Math.round(1.043 * Math.sqrt((this.wordsWithThreeSyllables(text) * (30 / this.sentenceCount(text))) + 3.1291) * 10) / 10;
};
TextStatistics.prototype.automatedReadabilityIndex = function (text) {
text = text ? cleanText(text) : this.text;
return Math.round(((4.71 * (this.letterCount(text) / this.wordCount(text))) + (0.5 * (this.wordCount(text) / this.sentenceCount(text))) - 21.43) * 10) / 10;
};
TextStatistics.prototype.textLength = function (text) {
text = text ? cleanText(text) : this.text;
return text.length;
};
TextStatistics.prototype.letterCount = function (text) {
text = text ? cleanText(text) : this.text;
text = text.replace(/[^a-z]+/ig, '');
return text.length;
};
TextStatistics.prototype.sentenceCount = function (text) {
text = text ? cleanText(text) : this.text;
// Will be tripped up by 'Mr.' or 'U.K.'. Not a major concern at this point.
return text.replace(/[^\.!?]/g, '').length || 1;
};
TextStatistics.prototype.wordCount = function (text) {
text = text ? cleanText(text) : this.text;
return text.split(/[^a-z0-9]+/i).length || 1;
};
TextStatistics.prototype.averageWordsPerSentence = function (text) {
text = text ? cleanText(text) : this.text;
return this.wordCount(text) / this.sentenceCount(text);
};
TextStatistics.prototype.averageSyllablesPerWord = function (text) {
text = text ? cleanText(text) : this.text;
var syllableCount = 0,
wordCount = this.wordCount(text),
self = this;
text.split(/\s+/).forEach(function (word) {
syllableCount += self.syllableCount(word);
});
// Prevent NaN...
return (syllableCount || 1) / (wordCount || 1);
};
TextStatistics.prototype.wordsWithThreeSyllables = function (text, countProperNouns) {
text = text ? cleanText(text) : this.text;
var longWordCount = 0,
self = this;
countProperNouns = countProperNouns === false ? false : true;
text.split(/\s+/).forEach(function (word) {
// We don't count proper nouns or capitalised words if the countProperNouns attribute is set.
// Defaults to true.
if (!word.match(/^[A-Z]/) || countProperNouns) {
if (self.syllableCount(word) > 2) longWordCount++;
}
});
return longWordCount;
};
TextStatistics.prototype.percentageWordsWithThreeSyllables = function (text, countProperNouns) {
text = text ? cleanText(text) : this.text;
return (this.wordsWithThreeSyllables(text, countProperNouns) / this.wordCount(text)) * 100;
};
TextStatistics.prototype.syllableCount = function (word) {
var syllableCount = 0,
prefixSuffixCount = 0,
wordPartCount = 0;
// Prepare word - make lower case and remove non-word characters
word = word.toLowerCase().replace(/[^a-z]/g, '');
// Specific common exceptions that don't follow the rule set below are handled individually
// Array of problem words (with word as key, syllable count as value)
var problemWords = {
'simile': 3,
'forever': 3,
'shoreline': 2
};
// Return if we've hit one of those...
if (problemWords.hasOwnProperty(word)) return problemWords[word];
// These syllables would be counted as two but should be one
var subSyllables = [
/cial/,
/tia/,
/cius/,
/cious/,
/giu/,
/ion/,
/iou/,
/sia$/,
/[^aeiuoyt]{2,}ed$/,
/.ely$/,
/[cg]h?e[rsd]?$/,
/rved?$/,
/[aeiouy][dt]es?$/,
/[aeiouy][^aeiouydt]e[rsd]?$/,
/^[dr]e[aeiou][^aeiou]+$/, // Sorts out deal, deign etc
/[aeiouy]rse$/ // Purse, hearse
];
// These syllables would be counted as one but should be two
var addSyllables = [
/ia/,
/riet/,
/dien/,
/iu/,
/io/,
/ii/,
/[aeiouym]bl$/,
/[aeiou]{3}/,
/^mc/,
/ism$/,
/([^aeiouy])\1l$/,
/[^l]lien/,
/^coa[dglx]./,
/[^gq]ua[^auieo]/,
/dnt$/,
/uity$/,
/ie(r|st)$/];
// Single syllable prefixes and suffixes
var prefixSuffix = [
/^un/,
/^fore/,
/ly$/,
/less$/,
/ful$/,
/ers?$/,
/ings?$/];
// Remove prefixes and suffixes and count how many were taken
prefixSuffix.forEach(function (regex) {
if (word.match(regex)) {
word = word.replace(regex, '');
prefixSuffixCount++;
}
});
wordPartCount = word.split(/[^aeiouy]+/ig)
.filter(function (wordPart) {
return !!wordPart.replace(/\s+/ig, '').length;
})
.length;
// Get preliminary syllable count...
syllableCount = wordPartCount + prefixSuffixCount;
// Some syllables do not follow normal rules - check for them
subSyllables.forEach(function (syllable) {
if (word.match(syllable)) syllableCount--;
});
addSyllables.forEach(function (syllable) {
if (word.match(syllable)) syllableCount++;
});
return syllableCount || 1;
};
function textStatistics(text) {
return new TextStatistics(text);
}
После принятия этой функции и добавления ее в code
Переменная (см. код Visual Basic OP) Я смог создать экземпляр этого элемента управления и вызвать методы для него. Есть несколько разных способов использования TextStatistics
в VBA:
Dim wc, sc As Integer
Dim s1, s2, code As String
Dim oTextStats As Object
Dim o As New ScriptControl
code = "function cleanText(e){var t=['li','p','h1','h2','h3','h4','h5','h6','dd'];t.forEach(function(t){e=e.replace('</'+t+'>','.')});e=e.replace(/<[^>]+>/g,'').replace(/[,:;()\-]/,' ').replace(/[\.!?]/,'.').replace(/^\s+/,'').replace(/[ ]*(\n|\r\n|\r)[ ]*/,' ').replace(/([\.])[\. ]+/,'.').replace(/[ ]*([\.])/,'. ').replace(/\s+/,' ').replace(/\s+$/,'');e+='.';return e}function textStatistics(e){return new TextStatistics(e)}if(!Array.prototype.filter){Array.prototype.filter=function(e){'use strict';if(this===void 0||this===null){throw new TypeError}var t=Object(this);" & _
"var n=t.length>>>0;if(typeof e!=='function'){throw new TypeError}var r=[];var i=arguments.length>=2?arguments[1]:void 0;for(var s=0;s<n;s++){if(s in t){var o=t[s];if(e.call(i,o,s,t)){r.push(o)}}}return r}}if(!Array.prototype.forEach){Array.prototype.forEach=function(e){var t=this.length;if(typeof e!='function')throw new TypeError;var n=arguments[1];for(var r=0;r<t;r++){if(r in this)e.call(n,this[r],r,this)}}}var TextStatistics=function(t){this.text=t?cleanText(t):this.text};" & _
"TextStatistics.prototype.fleschKincaidReadingEase=function(e){e=e?cleanText(e):this.text;return Math.round((206.835-1.015*this.averageWordsPerSentence(e)-84.6*this.averageSyllablesPerWord(e))*10)/10};TextStatistics.prototype.fleschKincaidGradeLevel=function(e){e=e?cleanText(e):this.text;return Math.round((.39*this.averageWordsPerSentence(e)+11.8*this.averageSyllablesPerWord(e)-15.59)*10)/10};TextStatistics.prototype.gunningFogScore=function(e){e=e?cleanText(e):this.text;" & _
"return Math.round((this.averageWordsPerSentence(e)+this.percentageWordsWithThreeSyllables(e,false))*.4*10)/10};TextStatistics.prototype.colemanLiauIndex=function(e){e=e?cleanText(e):this.text;return Math.round((5.89*(this.letterCount(e)/this.wordCount(e))-.3*(this.sentenceCount(e)/this.wordCount(e))-15.8)*10)/10};TextStatistics.prototype.smogIndex=function(e){e=e?cleanText(e):this.text;return Math.round(1.043*Math.sqrt(this.wordsWithThreeSyllables(e)*(30/this.sentenceCount(e))+3.1291)*10)/10};" & _
"TextStatistics.prototype.automatedReadabilityIndex=function(e){e=e?cleanText(e):this.text;return Math.round((4.71*(this.letterCount(e)/this.wordCount(e))+.5*(this.wordCount(e)/this.sentenceCount(e))-21.43)*10)/10};TextStatistics.prototype.textLength=function(e){e=e?cleanText(e):this.text;return e.length};TextStatistics.prototype.letterCount=function(e){e=e?cleanText(e):this.text;e=e.replace(/[^a-z]+/ig,'');return e.length};TextStatistics.prototype.sentenceCount=function(e){e=e?cleanText(e):this.text;" & _
"return e.replace(/[^\.!?]/g,'').length||1};TextStatistics.prototype.wordCount=function(e){e=e?cleanText(e):this.text;return e.split(/[^a-z0-9]+/i).length||1};TextStatistics.prototype.averageWordsPerSentence=function(e){e=e?cleanText(e):this.text;return this.wordCount(e)/this.sentenceCount(e)};TextStatistics.prototype.averageSyllablesPerWord=function(e){e=e?cleanText(e):this.text;var t=0,n=this.wordCount(e),r=this;e.split(/\s+/).forEach(function(e){t+=r.syllableCount(e)});return(t||1)/(n||1)};" & _
"TextStatistics.prototype.wordsWithThreeSyllables=function(e,t){e=e?cleanText(e):this.text;var n=0,r=this;t=t===false?false:true;e.split(/\s+/).forEach(function(e){if(!e.match(/^[A-Z]/)||t){if(r.syllableCount(e)>2)n++}});return n};TextStatistics.prototype.percentageWordsWithThreeSyllables=function(e,t){e=e?cleanText(e):this.text;return this.wordsWithThreeSyllables(e,t)/this.wordCount(e)*100};TextStatistics.prototype.syllableCount=function(e){var t=0,n=0,r=0;e=e.toLowerCase().replace(/[^a-z]/g,'');" & _
"var i={simile:3,forever:3,shoreline:2};if(i.hasOwnProperty(e))return i[e];var s=[/cial/,/tia/,/cius/,/cious/,/giu/,/ion/,/iou/,/sia$/,/[^aeiuoyt]{2,}ed$/,/.ely$/,/[cg]h?e[rsd]?$/,/rved?$/,/[aeiouy][dt]es?$/,/[aeiouy][^aeiouydt]e[rsd]?$/,/^[dr]e[aeiou][^aeiou]+$/,/[aeiouy]rse$/];var o=[/ia/,/riet/,/dien/,/iu/,/io/,/ii/,/[aeiouym]bl$/,/[aeiou]{3}/,/^mc/,/ism$/,/([^aeiouy])\1l$/,/[^l]lien/,/^coa[dglx]./,/[^gq]ua[^auieo]/,/dnt$/,/uity$/,/ie(r|st)$/];var u=[/^un/,/^fore/,/ly$/,/less$/,/ful$/,/ers?$/,/ings?$/];" & _
"u.forEach(function(t){if(e.match(t)){e=e.replace(t,'');n++}});r=e.split(/[^aeiouy]+/ig).filter(function(e){return!!e.replace(/\s+/ig,'').length}).length;t=r+n;s.forEach(function(n){if(e.match(n))t--});o.forEach(function(n){if(e.match(n))t++});return t||1}"
s1 = "the quick brown fox jumps over the lazy dog"
s2 = "help me! Some Short sentence fragments. Just a test"
With o
.Language = "JScript"
.AddCode code
' Create a TextStatistics object initially with no text.
' textStatistics is a function that creates TextStatistics objects
Set oTextStats = .Eval("textStatistics()")
' Now simply call TextStatistics methods directly
wc = oTextStats.wordCount(s1)
sc = oTextStats.sentenceCount(s2)
' Alternatively you can create a TextStatistics object with the text
' and call the methods with a blank string to return the values
' for the string passed in the constructor
Set oTextStats = .Eval("textStatistics('" + s1 + "')")
wc = oTextStats.wordCount("")
sc = oTextStats.sentenceCount("")
End With