2014-09-25 63 views
1

我試着從https://github.com/cgiffard/TextStatistics.js/blob/master/index.jsVBA JavaScript對象不支持此屬性或方法

得到文本統計功能在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轉換爲一組函數?

UPDATE: 略有不同的是使用的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/

更新:2014年1月10日 最終工作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 
+0

我想,但我得到錯誤的號碼argiments的 - 但讓我失望的另一條線路的調查 - 爲什麼不注入VBA瓦爾到的JavaScript函數 - 但是這給了我同樣的錯誤是JavaScript對象不支持這個屬性或方法 – Rob 2014-09-30 06:20:24

+0

即時通訊使用32位Excel 64位Win 7 – Rob 2014-09-30 06:20:52

+0

你是否能夠使用模塊頂部的Option Explicit編譯代碼?如果沒有,請檢查您的對象庫參考。 – Smandoli 2014-09-30 14:17:41

回答

2

我花了一些時間這一個下午學習Javascript,然後在微軟的ScriptControl對象中運行時試圖找出你的TextStatistics類正在發生什麼。我沒有從VBA中的破損代碼開始,而是回到OP參考的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方法:

這個方法是一個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); 
     } 
    }; 
} 

提供我原來的答覆後,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 
+0

很好地解決了問題... – 2014-10-01 04:27:46

+0

謝謝邁克爾 - 這個答案比我想要的要多! - 感謝您付出更多的努力 - 慷慨,真正值得的 – Rob 2014-10-01 07:55:23

+0

好的:我很快就說過了! :)下面的工作 - colemanLiauInde​​x,automatedReadabilityIndex,textLength,sentenceCount,letterCount,wordCount,averageWordsPerSentence - 下面不要smogIndex,wordsWithThreeSyllables,averageSyllablesPerWord,fleschKincaidReadingEase,fleschKincaidGradeLevel,gunningFogScore,我認爲它歸結爲音節功能...我將調查更多 – Rob 2014-10-01 08:42:11

相關問題