You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cognos Analytics 11.1.7IF9报表单值复制功能实现遇阻求助

Cognos Analytics 11.1.7IF9 报表单值复制问题

在网上搜索“Cognos report copy”会得到很多关于将报表规范复制到剪贴板的结果,但这并非本次问题的关注点。

使用Cognos Analytics的交互式查看器时,用户无法选择报表中的文本并复制到其他应用。有用户提出需求,希望能将报表输出中的单个值复制到剪贴板。

由于报表具备一些交互功能,优先选择将报表生成为HTML输出格式,生成PDF会增加额外工作量。

我可以编写一个包含脚本的网页,实现点击指定元素将其内容复制到剪贴板的功能:

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
$(document).ready(function(){
  var arr = ["city", "country"];
  arr.forEach(function(e){
    $("span[lid='" + e + "']").click(function() {
      navigator.clipboard.writeText($(this).html());
    });
  });
});
</script>
</head>
<body>

<span lid="city">Click me to copy my City contents to the clipboard.</span><br /><br />
<span lid="country">Click me to copy my Country contents to the clipboard.</span><br /><br />
<span lid="region">Region contents are not copied</span><br /><br />
<span>I also do nothing</span><br /><br />

</body>
</html>

但在Cognos中尝试此方法并未成功。我创建了一个示例报表:

<report xmlns="http://developer.cognos.com/schemas/report/15.5/" useStyleVersion="11.6" expressionLocale="en-us">
    <drillBehavior/>
    <layouts>
        <layout>
            <reportPages>
                <page name="Page1">
                    <style>
                        <defaultStyles>
                            <defaultStyle refStyle="pg"/>
                        </defaultStyles>
                    </style>
                    <pageBody>
                        <style>
                            <defaultStyles>
                                <defaultStyle refStyle="pb"/>
                            </defaultStyles>
                        </style>
                        <contents>
                            <list horizontalPagination="true" name="List1" refQuery="Query1" rowsPerPage="9999">
                                <noDataHandler>
                                    <contents>
                                        <block>
                                            <contents>
                                                <textItem>
                                                    <dataSource>
                                                        <staticValue>No Data Available</staticValue>
                                                    </dataSource>
                                                </textItem>
                                            </contents>
                                            <style>
                                                <CSS value="padding:16px;"/>
                                            </style>
                                        </block>
                                    </contents>
                                </noDataHandler>
                                <style>
                                    <CSS value="border-collapse:collapse"/>
                                    <defaultStyles>
                                        <defaultStyle refStyle="ls"/>
                                    </defaultStyles>
                                </style>
                                <listColumns>
                                    <listColumn>
                                        <listColumnTitle>
                                            <style>
                                                <defaultStyles>
                                                    <defaultStyle refStyle="lt"/>
                                                </defaultStyles>
                                            </style>
                                            <contents>
                                                <textItem>
                                                    <dataSource>
                                                        <dataItemLabel refDataItem="City"/>
                                                    </dataSource>
                                                </textItem>
                                            </contents>
                                        </listColumnTitle>
                                        <listColumnBody>
                                            <style>
                                                <defaultStyles>
                                                    <defaultStyle refStyle="lc"/>
                                                </defaultStyles>
                                            </style>
                                            <contents>
                                                <textItem name="city">
                                                    <dataSource>
                                                        <dataItemValue refDataItem="City"/>
                                                    </dataSource>
                                                </textItem>
                                            </contents>
                                        </listColumnBody>
                                    </listColumn>
                                    <listColumn>
                                        <listColumnTitle>
                                            <style>
                                                <defaultStyles>
                                                    <defaultStyle refStyle="lt"/>
                                                </defaultStyles>
                                            </style>
                                            <contents>
                                                <textItem>
                                                    <dataSource>
                                                        <dataItemLabel refDataItem="Year"/>
                                                    </dataSource>
                                                </textItem>
                                            </contents>
                                        </listColumnTitle>
                                        <listColumnBody>
                                            <style>
                                                <defaultStyles>
                                                    <defaultStyle refStyle="lc"/>
                                                </defaultStyles>
                                            </style>
                                            <contents>
                                                <textItem>
                                                    <dataSource>
                                                        <dataItemValue refDataItem="Year"/>
                                                    </dataSource>
                                                </textItem>
                                            </contents>
                                        </listColumnBody>
                                    </listColumn>
                                    <listColumn>
                                        <listColumnTitle>
                                            <style>
                                                <defaultStyles>
                                                    <defaultStyle refStyle="lt"/>
                                                </defaultStyles>
                                            </style>
                                            <contents>
                                                <textItem>
                                                    <dataSource>
                                                        <dataItemLabel refDataItem="Revenue"/>
                                                    </dataSource>
                                                </textItem>
                                            </contents>
                                        </listColumnTitle>
                                        <listColumnBody>
                                            <style>
                                                <defaultStyles>
                                                    <defaultStyle refStyle="lm"/>
                                                </defaultStyles>
                                            </style>
                                            <contents>
                                                <textItem>
                                                    <dataSource>
                                                        <dataItemValue refDataItem="Revenue"/>
                                                    </dataSource>
                                                </textItem>
                                            </contents>
                                        </listColumnBody>
                                    </listColumn>
                                </listColumns>
                                <sortList>
                                    <sortItem refDataItem="City"/>
                                    <sortItem refDataItem="Year"/>
                                </sortList>
                            </list>
                            <customControl path="/CognosScripts/Copy.js">
                                <configuration>{
    &quot;SpansToCopy&quot;: [
        &quot;city&quot;
    ]
}</configuration>
                            </customControl>
                        </contents>
                    </pageBody>
                    <XMLAttributes>
                        <XMLAttribute output="no" name="RS_legacyDrillDown" value="0"/>
                    </XMLAttributes>
                </page>
            </reportPages>
        </layout>
    </layouts>
    <XMLAttributes>
        <XMLAttribute output="no" name="RS_CreateExtendedDataItems" value="true"/>
        <XMLAttribute output="no" name="listSeparator" value=","/>
        <XMLAttribute output="no" name="decimalSeparator" value="."/>
        <XMLAttribute output="no" name="RS_modelModificationTime" value="2015-11-25T21:38:24.820Z"/>
    </XMLAttributes>
    <queries>
        <query name="Query1">
            <source>
                <model/>
            </source>
            <selection>
                <dataItem aggregate="none" rollupAggregate="none" name="City">
                    <expression>[Sales (query)].[Branch].[City]</expression>
                    <XMLAttributes>
                        <XMLAttribute output="no" name="RS_dataType" value="3"/>
                        <XMLAttribute output="no" name="RS_dataUsage" value="0"/>
                    </XMLAttributes>
                </dataItem>
                <dataItem aggregate="total" name="Revenue">
                    <expression>[Sales (query)].[Sales].[Revenue]</expression>
                    <XMLAttributes>
                        <XMLAttribute output="no" name="RS_dataType" value="2"/>
                        <XMLAttribute output="no" name="RS_dataUsage" value="2"/>
                    </XMLAttributes>
                </dataItem>
                <dataItem aggregate="none" rollupAggregate="none" name="Year">
                    <expression>[Sales (query)].[Time].[Year]</expression>
                    <XMLAttributes>
                        <XMLAttribute output="no" name="RS_dataType" value="1"/>
                        <XMLAttribute output="no" name="RS_dataUsage" value="0"/>
                    </XMLAttributes>
                </dataItem>
            </selection>
        </query>
    </queries>
    <modelPath>/content/folder[@name=&amp;apos;Samples&amp;apos;]/folder[@name=&amp;apos;Models&amp;apos;]/package[@name=&amp;apos;GO sales (query)&amp;apos;]/model[@name=&amp;apos;model&amp;apos;]</modelPath>
    <reportName>copy</reportName>
</report>

...并添加了一个自定义控件:

define( ["jquery"], function() {
    "use strict";
    
    var log = function (label, message) {
        console.log("    ****    Copy :  " + label + " : " + message);
    };
    
    function Copy() {};
    
    Copy.prototype.initialize = function( oControlHost, fnDoneInitializing ) {
        log("Copy", "Control.initialize" );
        
        /*
        Sample Configuration:
        {
            "SpansToCopy": ["city", "country"]
        }
        
        If I name a text item in the report, the resulting span is given an attribute named "lid".
        */
    
        this.controlHost = oControlHost;
        this.oConfig = this.controlHost.configuration;
        
        $(document).ready(function(){
            this.oConfig.SpansToCopy.forEach(function(e){
                $("span[lid='" + e + "']").click(function() {
                    navigator.clipboard.writeText($(this).html());
                });
            });
        });
        
        fnDoneInitializing();
    };
    
    Copy.prototype.draw = function( oControlHost ) {};
    
    return Copy;
});

运行时出现以下错误:

jQuery.Deferred exception: e is not a function TypeError: e is not a function

该错误在$(document).ready函数运行时触发。


问题解答

1. 核心错误:作用域问题

在$(document).ready的回调函数中,this指向的是document对象,而非Copy控件实例,导致this.oConfig为undefined。调用undefined.SpansToCopy.forEach时自然抛出错误(本质是对undefined调用forEach方法)。

修复方法:提前保存当前实例的引用

Copy.prototype.initialize = function( oControlHost, fnDoneInitializing ) {
    log("Copy", "Control.initialize" );

    this.controlHost = oControlHost;
    this.oConfig = this.controlHost.configuration;
    var self = this; // 保存当前实例引用
    
    $(document).ready(function(){
        self.oConfig.SpansToCopy.forEach(function(e){
            $("span[lid='" + e + "']").click(function() {
                navigator.clipboard.writeText($(this).html());
            });
        });
    });
    
    fnDoneInitializing();
};

若Cognos环境支持ES6,也可使用箭头函数(继承外部作用域的this):

$(document).ready(() => {
    this.oConfig.SpansToCopy.forEach(e => {
        $("span[lid='" + e + "']").click(() => {
            navigator.clipboard.writeText($(this).html());
        });
    });
});

2. jQuery版本兼容性说明

Cognos Analytics 11.1.7内置的jQuery通常为1.x或2.x,你测试用的是3.6.0,但本次错误并非版本兼容导致。不过需注意:

  • 内置jQuery可能不支持箭头函数,优先用保存self变量的方式。
  • navigator.clipboard是HTML5 API,部分旧浏览器不支持,可改用传统复制方法:
$("span[lid='" + e + "']").click(function() {
    var $temp = $("<textarea>");
    $("body").append($temp);
    $temp.val($(this).text()).select();
    document.execCommand("copy");
    $temp.remove();
});

3. 其他实现复制需求的方案

除修复自定义控件,还有以下可行方法:

  • 添加复制按钮:在每个可复制字段旁添加自定义按钮,点击触发复制逻辑,避免和报表原有交互冲突,更直观。
  • 启用文本选择:调整报表HTML输出的样式,移除user-select:none这类禁止文本选择的CSS规则,让用户直接选中文本复制。
  • 导出到Excel/CSV:提供导出选项,用户导出数据后再复制所需值,适合批量复制场景。
  • Cognos SDK定制:通过SDK编写服务器端逻辑,实现点击复制指定字段值,不过开发成本较高。

内容的提问来源于stack exchange,提问作者dougp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 08:33:27