我试图从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
我得到的对象不支持这个属性或方法 - 我认为它是由于Text Statistics的实例化。
我是否需要将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/
更新:01/10/2014 最终工作VBA版本归功于Michael Petch
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
答案 0 :(得分:2)
我今天下午花了一些时间学习Javascript,然后在Microsoft的TextStatistics
对象中运行时试图弄清楚ScriptControl
课程的内容。而不是从VBA中的受损代码开始,我回到了引用的github中的代码。我发现的第一件事是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。一旦我完成了这项工作,我就找到了与此information的链接,其中包含以下评论:关于forEach
方法:
此方法是ECMA-262标准的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);
}
};
}
在提供我的原始答案后,OP发现涉及音节的功能不起作用。还有一个函数出现在后来的ECMA规范中ScriptControl
不支持。这就是数组上的polyfill filter
函数。根据这个Mozilla documentation:
过滤器已添加到第5版的ECMA-262标准中;因此,它可能不存在于标准的所有实现中。您可以通过在脚本开头插入以下代码来解决此问题,允许在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
变量后(参见OP的Visual Basic代码),我能够创建此控件的实例并在其上调用方法。在VBA中使用TextStatistics
有几种不同的方法:
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