找回密码
 立即注册

QQ登录

只需一步,快速开始

[已处理] Spread打印问题。

bingdaoice
中级会员   /  发表于:2021-2-1 14:53  /   查看:6319  /  回复:15
1金币
本帖最后由 bingdaoice 于 2021-2-1 14:54 编辑

使用PrintSheet进行打印的4种方法,不管是使用线程打印,还是使用当前进程打印都会报错。(多数为打印第二次时报错。附件有DEMO可下载直接测试重现问题。)

        private void btnPrint_Click(object sender, EventArgs e)
        {
            //如果将此放在FOR里面会报“System.InvalidOperationException”类型的未经处理的异常在 System.Windows.Forms.dll 中发生 其他信息: 线程间操作无效: 从不是创建控件“”的线程访问它。
            FarPoint.Win.Spread.FpSpread fpSpread1 = new FarPoint.Win.Spread.FpSpread();

            for (int i = 1; i <= 500; i++)
            {
                //这里现实情况是会打开不同的文件,所以必须放在FOR里面。因为论坛上传不能超过20M所以才用1个文件进行循环打开进行测试。
                fpSpread1.Open(AppDomain.CurrentDomain.BaseDirectory + "1.xml");

                string PrinterName = "检定证书";
                if (fpSpread1.GetPrintPageCount(1) > 2)//获取需要打印文件的页数来判断是否需要把任务发送到有装订功能的打印机上进行打印及装订。
                    PrinterName = PrinterName + "多页";

                fpSpread1.Sheets[1].PrintInfo.Preview = false;//是否预览


                //这个设置打印机名称,需要根据任务把文件发送到不同的打印机上进行打印
                //现实情况中,我们有3种证书加3种证书带装订的,总共是6个打印机名称,需要根据不同的证书类型。把打印任务发送到匹配的打印机上,才能打印出正确的证书。
                //举例我们有检定证书和校准证书,两种证书的章是不一样的。就有两个打印机,打印检定证书时,需要用检定证书的纸张,反之校准证书需要把任务发送到校准证书打印机上进行打印。
                //而且我们有多页的情况下还需要把任务发送到“检定证书多页”的打印机上,有多页的情况下打印机设定了自动装订功能,打印出来的证书会自动装订。
                //反之如果没有多页的情况下就不需要装订,就不会把任务发送到“检定证书多页”的打印机上。而是发送到"检定证书"打印机上进行打印。不进行装订的打印速度会快1秒左右出来,提高效率。
                fpSpread1.Sheets[1].PrintInfo.Printer = PrinterName;

                //打印任务名称,当打印数量较多时很有用,比如打印机出现问题,我们可以通过查看哪些打印任务未打印,判断这些证书是否需要继续打印。
                //因为当任务发送给打印机之后,在系统里面会标记为已打印。
                //但实际情况是任务发送给打印机之后,打印机出问题了,证书没有打印出来。如果任务列表没有文件名称进行判别的话,就无法判断出哪些文件实际上没有打印出来。
                fpSpread1.Sheets[1].PrintInfo.JobName = i.ToString();



                //如果只将fpSpread1.PrintSheet放在FOR里面进行循环打印,与实际情况不符。
                //因为现实情况是会打开不同的文件,进行打印。
                //我们的实际情况是一天大约会打印3000张证书左右,就是打印3000份不同的文件。而不是1份文件打印3000次。
                //所以不能只将fpSpread1.PrintSheet放到FOR里面进行循环
                //打印想达到的就是:想打印就打印,想暂停就暂停。想取消就取消。
                //现在是4种打印模式打印2次或2次以上都会报错,无法继续打印。只能关闭程序后重新操作打。

                //fpSpread1.PrintSheet(fpSpread1.Sheets[1]);//速度1秒1张。打印约20张左右报会报“System.Exception”类型的未经处理的异常在 FarPoint.Win.Spread.dll 中发生 其他信息: The index -1 is not between 0 and 2.
                //fpSpread1.PrintSheet(1);//速度1秒1张。打印约200张左右报会报“System.Exception”类型的未经处理的异常在 FarPoint.Win.Spread.dll 中发生 其他信息: The index 1 is not between 0 and 1.
                fpSpread1.PrintSheet(1, true);//速度1秒1张。打印第二次时会报“System.Exception”类型的未经处理的异常在 FarPoint.Win.Spread.dll 中发生   其他信息: The index 1 is not between 0 and 1.                //“System.NullReferenceException”类型的未经处理的异常在 GrapeCity.Spreadsheet.dll 中发生 其他信息: 未将对象引用设置到对象的实例。
                //fpSpread1.PrintSheet(1, false);//速度4秒1张。使用此方式打印会报“System.ArgumentException”类型的未经处理的异常在 System.Drawing.dll 中发生 其他信息: 参数无效。
            }
            MessageBox.Show("进程打印完毕");
        }

spread_win_打印问题.rar

16.21 MB, 下载次数: 123

15 个回复

正序浏览
Richard.Ma讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2021-2-9 00:33:50
16#
这两种方法实际上是一种,而且不是异步打印,并不会提高现在的速度,建议你暂时不用考虑这两种方法
此问题会作为bug提交给研发人员,有处理结果后会在此回复更新
回复 使用道具 举报
KevinChen讲师达人认证 悬赏达人认证 SpreadJS 开发认证
论坛元老   /  发表于:2021-2-8 11:51:15
15#
您好,问题已收到,预计明天给您回复,感谢反馈~
回复 使用道具 举报
bingdaoice
中级会员   /  发表于:2021-2-8 11:31:23
14#
那么请问使用fpSpread1.PrintSheet(1)和fpSpread1.PrintSheet(fpSpread1.Sheets[1]); 这两种打印数量过多会报错的问题会解决吗?
回复 使用道具 举报
Richard.Ma讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2021-2-7 22:31:53
13#
抱歉,目前没有其他的办法可以提高打印速度了
回复 使用道具 举报
KevinChen讲师达人认证 悬赏达人认证 SpreadJS 开发认证
论坛元老   /  发表于:2021-2-7 14:15:21
12#
您好,问题已收到,预计明天给您回复,感谢反馈~
回复 使用道具 举报
bingdaoice
中级会员   /  发表于:2021-2-7 13:56:55
11#
谢谢,已测试出使用fpSpread1.Invoke(new Action(() => { fpSpread1.PrintSheet(1, true); }))此种方式可以一直打印了。
但有另一问题出现了,此方式打印文件时需要4秒左右才能打印一份。
1分钟只能打15份左右。
其它方式fpSpread1.PrintSheet(1);这个速度到是快。但不能连续打印。
不知道有没有提高打印速度的方法?
回复 使用道具 举报
Richard.Ma讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2021-2-3 16:58:49
10#
我看了你的代码,如果你说的报错是“针对此 RuntimeCallableWrapper 向 COM 上下文 XXXXX 的转换失败”,这类错误的话
注释掉代码中的这一句就行
t1.SetApartmentState(System.Threading.ApartmentState.STA);

回复 使用道具 举报
bingdaoice
中级会员   /  发表于:2021-2-3 14:39:23
9#
本帖最后由 bingdaoice 于 2021-2-3 14:45 编辑
Richard.Ma 发表于 2021-2-3 11:49
这个两个事件是不需要的,已修改删除楼上的代码,最重要的就是将打印包含再Invoke中

版主,能不能用我现在附件提供的DEMO测试一下。
我使用了2个方法:12种方法打印,都会报错。方法1:
fpSpread1.CreateControl();fpSpread1.Invoke(new Action(() => { fpSpread1.PrintSheet(1, false); }));


方法2:
Control.CheckForIllegalCrossThreadCalls = false;
fpSpread1.PrintSheet(1, false);

附件中有我的DEMO,请使用此DEMO进行测试。
请测试达到5000打印次数不报错为正常。因为我们现实情况是一天的打印量约为3000-4000张左右。

spread_win_打印问题.rar

18.37 MB, 下载次数: 395

回复 使用道具 举报
Richard.Ma讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2021-2-3 11:49:17
8#
这个两个事件是不需要的,已修改删除楼上的代码,最重要的就是将打印包含再Invoke中

  1. fpSpread1.Invoke(new Action(() => {
  2.                     fpSpread1.PrintSheet(1, false);
  3.                 }));
复制代码
回复 使用道具 举报
bingdaoice
中级会员   /  发表于:2021-2-3 11:30:11
7#
Richard.Ma 发表于 2021-2-2 16:58
你好,在调用打印方法之前,调用这个代码可以完全解决“从不是创建控件的线程访问它”的问题

请问  fpSpread1.PrintAbort += FpSpread1_PrintAbort;
                fpSpread1.PrintCancelled += FpSpread1_PrintCancelled;这两个事件里面的代码是什么?
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 立即注册
返回顶部