找回密码
 立即注册

QQ登录

只需一步,快速开始

[已处理] Spread打印问题。

bingdaoice
中级会员   /  发表于:2021-2-1 14:53  /   查看:6165  /  回复: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-1 15:33:31
沙发
可以按照此附件运行测试

spreadprint.zip

17.67 MB, 下载次数: 547

回复 使用道具 举报
bingdaoice
中级会员   /  发表于:2021-2-1 15:41:31
板凳
本帖最后由 bingdaoice 于 2021-2-1 15:47 编辑
Richard.Ma 发表于 2021-2-1 15:33
可以按照此附件运行测试

版主你好。你的这个代码与我实际使用方式是不一样的。你的代码是将同一份文件打印100次。而我是需要加载100份不同的文件,打印100次。(只不过是论坛上传要求限制20M,所以才用同一个文件循环加载来进行打印测试。)
这两个要求是不一样的。

for (int i = 1; i <= 100; i++)
            {
                while (Suspend == true)
                {
                }
                if (Stop == true)
                    break;
                fpSpread1.PrintSheet(1, false);
            }

而且在我这边测使使用你上面的DEMO,打印第三次时也报“System.InvalidOperationException”类型的未经处理的异常在 System.Windows.Forms.dll 中发生
其他信息: 线程间操作无效: 从不是创建控件“”的线程访问它。你可以多点几次打印试试,应该也会报错的。
image.png488262328.png



回复 使用道具 举报
Richard.Ma讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2021-2-1 17:55:48
地板
收到,我再测试一下 重新给你发一个demo过去
回复 使用道具 举报
bingdaoice
中级会员   /  发表于:2021-2-2 14:41:13
5#
你好,请问测试有结果了吗?
回复 使用道具 举报
Richard.Ma讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2021-2-2 16:58:45
6#
本帖最后由 Richard.Ma 于 2021-2-3 11:48 编辑

你好,在调用打印方法之前,调用这个代码可以完全解决“从不是创建控件的线程访问它”的问题

  1. Control.CheckForIllegalCrossThreadCalls = false;
复制代码


image.png56889647.png

另一个办法的话,还是我之前帖子中给你提到的,通过委托来打印
  1.             for (int i = 1; i <= 8; i++)
  2.             {
  3.                 while (Suspend == true)
  4.                 {
  5.                 }
  6.                 if (Stop == true)
  7.                     break;
  8.                 fpSpread1.CreateControl();
  9.                 fpSpread1.Invoke(new Action(() => {
  10.                     fpSpread1.PrintSheet(1, false);
  11.                 }));
  12.             }
复制代码





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

请问  fpSpread1.PrintAbort += FpSpread1_PrintAbort;
                fpSpread1.PrintCancelled += FpSpread1_PrintCancelled;这两个事件里面的代码是什么?
回复 使用道具 举报
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 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 16:58:49
10#
我看了你的代码,如果你说的报错是“针对此 RuntimeCallableWrapper 向 COM 上下文 XXXXX 的转换失败”,这类错误的话
注释掉代码中的这一句就行
t1.SetApartmentState(System.Threading.ApartmentState.STA);

回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 立即注册
返回顶部