c# 通过句柄获取已经打开的excel表中的值

我是翔子 2015-01-30 10:54:33
相当于是一个excel外挂,网上搜的资料都是需要先把excel导入进c#

但目前的需求是,一个c# winform需要轮询进程列表,当找到有excel进程时,自动将excel表中单元格内的值取出来。。。

各位大侠。。该如何做。。不胜感激
...全文
510 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
qwprince 2015-02-01
  • 打赏
  • 举报
回复
谢谢wyd1520的回复,正巧我也在和楼主一样,在发愁怎样实时获取excel表格中的数据,多谢多谢,明天赶紧试一下,同时也谢谢楼主
我是翔子 2015-01-30
  • 打赏
  • 举报
回复
楼上挺强大。。。待我细细测来
本拉灯 2015-01-30
  • 打赏
  • 举报
回复
楼主不需要用语句柄了,直接下面的代码 就能取出打开的EXCEL在进程中所有的文件了,包含能取到的路径和内容, 只要取到 Microsoft.Office.Interop.Excel.Application a = o as Microsoft.Office.Interop.Excel.Application; 这个对像,你就能为所欲为了,怎么操作EXCEL都成。剩下的就是你要去了解这个对像的操作EXCEL的方式。

[DllImport("ole32.dll")]
        public static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);

        [DllImport("ole32.dll")]
        public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc);


        private Hashtable GetRunningObjectTable()
        {
            Hashtable result = new Hashtable();

            IntPtr numFetched = IntPtr.Zero;
            IRunningObjectTable runningObjectTable;
            IEnumMoniker monikerEnumerator;
            IMoniker[] monikers = new IMoniker[1];
            GetRunningObjectTable(0, out runningObjectTable);
            runningObjectTable.EnumRunning(out monikerEnumerator);
            monikerEnumerator.Reset();
            while (monikerEnumerator.Next(1, monikers, numFetched) == 0)
            {
                IBindCtx ctx;
                CreateBindCtx(0, out ctx);
                string runningObjectName;monikers[0].GetDisplayName(ctx, null, out runningObjectName);
                object runningObjectVal;
                runningObjectTable.GetObject(monikers[0], outrunningObjectVal);
                result[runningObjectName] = runningObjectVal;
            }
            return result;
        }

        private bool XlsIsOpen(string fileName)
        {
            bool XlsIsOpen = false;
            Hashtable rot = GetRunningObjectTable();
            bool isOk = false;
            foreach (object o in rot.Values)
            {
                if (isOk)
                {
                    break;
                }
                Microsoft.Office.Interop.Excel.Application a = o as Microsoft.Office.Interop.Excel.Application;
                if (a != null)
                {
                    Microsoft.Office.Interop.Excel.Workbooks wbooks = a.Workbooks;
                    foreach (Microsoft.Office.Interop.Excel.Workbook wb in wbooks)
                    {
                       
                        if (wb.Name == fileName)
                        {
                            Microsoft.Office.Interop.Excel.Worksheet sheet = wb.ActiveSheet as Microsoft.Office.Interop.Excel.Worksheet;


                            int iRowCount = sheet.UsedRange.Rows.Count;
                            int iColCount = sheet.UsedRange.Columns.Count;
                            Microsoft.Office.Interop.Excel.Range range;

                            for (int iRow = 1; iRow <= iRowCount; iRow++)
                            {


                                for (int iCol = 1; iCol <= iColCount; iCol++)
                                {

                                    Microsoft.Office.Interop.Excel.Range ss = (Microsoft.Office.Interop.Excel.Range)sheet.Cells[iRow, iCol];
                                    Console.WriteLine(ss.Text);
                                }
                            }
                            XlsIsOpen = true;
                            isOk = true;
                            break;
                        }
                    }
                    //a.DisplayAlerts = false;
                    //a.Quit();
                }
            }
            return XlsIsOpen;

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            XlsIsOpen(@"XX.xls");
        }
我是翔子 2015-01-30
  • 打赏
  • 举报
回复
我给大家上个图吧。。。

客户是用vba开发出来的excel,文档里有一些按钮,最初的情况是客户要手动依次点击按钮和他们的上位机交互,最后得出一个最终的值显示在一个单元格内,我现在做的这个就是,代替客户手动去点击那些excel中的按钮,并将最终的单元格内的值取到

蜗牛慢慢趴 2015-01-30
  • 打赏
  • 举报
回复
引用 5 楼 wyd1520 的回复:
这个有难度。。。 [quote=引用 4 楼 xiangmei521 的回复:] [quote=引用 3 楼 q644415569 的回复:] [quote=引用 2 楼 xiangmei521 的回复:] [quote=引用 1 楼 q644415569 的回复:] 你的意思是我打开程序 如果任务管理器里面有excel时候直接去抓Excel里面的内容吗
恩恩,对的,我这边的需求就是,当excel打开的时候,做一些自动化的处理[/quote] windows自带的任务管理器好像无法直接找到当前打开文件的位置[/quote] 我不需要找到excel文件的位置,winform程序是开机自启动的,系统一启动这个winform就开始轮询进程列表,如果有excel文件被用户双击打开,这时候winform就开始自动获取单元格里的内容,并通过tcp/ip将值传送给上位机,通信这块没什么问题,关键是如果取到单元格内的值。 在进程列表中找到excel的话,就能取到excel的句柄,得到句柄之后能取出值吗[/quote] 这好像MS没有提供这样的接口,[/quote] 如果有这样的接口 那万一用户电脑被我植入一个开机启动程序,那我就可以直接找到所有他打开的文件内容了.这个是不是有点夸张了
蜗牛慢慢趴 2015-01-30
  • 打赏
  • 举报
回复
本拉灯 2015-01-30
  • 打赏
  • 举报
回复
这个有难度。。。
引用 4 楼 xiangmei521 的回复:
[quote=引用 3 楼 q644415569 的回复:] [quote=引用 2 楼 xiangmei521 的回复:] [quote=引用 1 楼 q644415569 的回复:] 你的意思是我打开程序 如果任务管理器里面有excel时候直接去抓Excel里面的内容吗
恩恩,对的,我这边的需求就是,当excel打开的时候,做一些自动化的处理[/quote] windows自带的任务管理器好像无法直接找到当前打开文件的位置[/quote] 我不需要找到excel文件的位置,winform程序是开机自启动的,系统一启动这个winform就开始轮询进程列表,如果有excel文件被用户双击打开,这时候winform就开始自动获取单元格里的内容,并通过tcp/ip将值传送给上位机,通信这块没什么问题,关键是如果取到单元格内的值。 在进程列表中找到excel的话,就能取到excel的句柄,得到句柄之后能取出值吗[/quote] 这好像MS没有提供这样的接口,
我是翔子 2015-01-30
  • 打赏
  • 举报
回复
引用 3 楼 q644415569 的回复:
[quote=引用 2 楼 xiangmei521 的回复:] [quote=引用 1 楼 q644415569 的回复:] 你的意思是我打开程序 如果任务管理器里面有excel时候直接去抓Excel里面的内容吗
恩恩,对的,我这边的需求就是,当excel打开的时候,做一些自动化的处理[/quote] windows自带的任务管理器好像无法直接找到当前打开文件的位置[/quote] 我不需要找到excel文件的位置,winform程序是开机自启动的,系统一启动这个winform就开始轮询进程列表,如果有excel文件被用户双击打开,这时候winform就开始自动获取单元格里的内容,并通过tcp/ip将值传送给上位机,通信这块没什么问题,关键是如果取到单元格内的值。 在进程列表中找到excel的话,就能取到excel的句柄,得到句柄之后能取出值吗
蜗牛慢慢趴 2015-01-30
  • 打赏
  • 举报
回复
引用 2 楼 xiangmei521 的回复:
[quote=引用 1 楼 q644415569 的回复:] 你的意思是我打开程序 如果任务管理器里面有excel时候直接去抓Excel里面的内容吗
恩恩,对的,我这边的需求就是,当excel打开的时候,做一些自动化的处理[/quote] windows自带的任务管理器好像无法直接找到当前打开文件的位置
我是翔子 2015-01-30
  • 打赏
  • 举报
回复
引用 1 楼 q644415569 的回复:
你的意思是我打开程序 如果任务管理器里面有excel时候直接去抓Excel里面的内容吗
恩恩,对的,我这边的需求就是,当excel打开的时候,做一些自动化的处理
蜗牛慢慢趴 2015-01-30
  • 打赏
  • 举报
回复
你的意思是我打开程序 如果任务管理器里面有excel时候直接去抓Excel里面的内容吗
我是翔子 2015-01-30
  • 打赏
  • 举报
回复
引用 12 楼 wyd1520 的回复:
[quote=引用 11 楼 xiangmei521 的回复:] 经测试,能把值取出来。。。但是还有个问题,怎么能触发上面截图中的四个按钮啊。。。
这与标题不符,不回答,只给你个提示你用录制宏的式,录制一个点击的效果出来。然后去查里面宏的原码那段点击的代码段。再转换成C#的代码。 上面说了拿到了Excel.ApplicationClass怎么整都可以了,这跟Excel里面的处里宏是一样的。[/quote] ok结贴,我得把你关注一下
本拉灯 2015-01-30
  • 打赏
  • 举报
回复
引用 11 楼 xiangmei521 的回复:
经测试,能把值取出来。。。但是还有个问题,怎么能触发上面截图中的四个按钮啊。。。
这与标题不符,不回答,只给你个提示你用录制宏的式,录制一个点击的效果出来。然后去查里面宏的原码那段点击的代码段。再转换成C#的代码。 上面说了拿到了Excel.ApplicationClass怎么整都可以了,这跟Excel里面的处里宏是一样的。
我是翔子 2015-01-30
  • 打赏
  • 举报
回复
引用 9 楼 wyd1520 的回复:
楼主不需要用语句柄了,直接下面的代码 就能取出打开的EXCEL在进程中所有的文件了,包含能取到的路径和内容, 只要取到 Microsoft.Office.Interop.Excel.Application a = o as Microsoft.Office.Interop.Excel.Application; 这个对像,你就能为所欲为了,怎么操作EXCEL都成。剩下的就是你要去了解这个对像的操作EXCEL的方式。

[DllImport("ole32.dll")]
        public static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);

        [DllImport("ole32.dll")]
        public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc);


        private Hashtable GetRunningObjectTable()
        {
            Hashtable result = new Hashtable();

            IntPtr numFetched = IntPtr.Zero;
            IRunningObjectTable runningObjectTable;
            IEnumMoniker monikerEnumerator;
            IMoniker[] monikers = new IMoniker[1];
            GetRunningObjectTable(0, out runningObjectTable);
            runningObjectTable.EnumRunning(out monikerEnumerator);
            monikerEnumerator.Reset();
            while (monikerEnumerator.Next(1, monikers, numFetched) == 0)
            {
                IBindCtx ctx;
                CreateBindCtx(0, out ctx);
                string runningObjectName;monikers[0].GetDisplayName(ctx, null, out runningObjectName);
                object runningObjectVal;
                runningObjectTable.GetObject(monikers[0], outrunningObjectVal);
                result[runningObjectName] = runningObjectVal;
            }
            return result;
        }

        private bool XlsIsOpen(string fileName)
        {
            bool XlsIsOpen = false;
            Hashtable rot = GetRunningObjectTable();
            bool isOk = false;
            foreach (object o in rot.Values)
            {
                if (isOk)
                {
                    break;
                }
                Microsoft.Office.Interop.Excel.Application a = o as Microsoft.Office.Interop.Excel.Application;
                if (a != null)
                {
                    Microsoft.Office.Interop.Excel.Workbooks wbooks = a.Workbooks;
                    foreach (Microsoft.Office.Interop.Excel.Workbook wb in wbooks)
                    {
                       
                        if (wb.Name == fileName)
                        {
                            Microsoft.Office.Interop.Excel.Worksheet sheet = wb.ActiveSheet as Microsoft.Office.Interop.Excel.Worksheet;


                            int iRowCount = sheet.UsedRange.Rows.Count;
                            int iColCount = sheet.UsedRange.Columns.Count;
                            Microsoft.Office.Interop.Excel.Range range;

                            for (int iRow = 1; iRow <= iRowCount; iRow++)
                            {


                                for (int iCol = 1; iCol <= iColCount; iCol++)
                                {

                                    Microsoft.Office.Interop.Excel.Range ss = (Microsoft.Office.Interop.Excel.Range)sheet.Cells[iRow, iCol];
                                    Console.WriteLine(ss.Text);
                                }
                            }
                            XlsIsOpen = true;
                            isOk = true;
                            break;
                        }
                    }
                    //a.DisplayAlerts = false;
                    //a.Quit();
                }
            }
            return XlsIsOpen;

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            XlsIsOpen(@"XX.xls");
        }
经测试,能把值取出来。。。但是还有个问题,怎么能触发上面截图中的四个按钮啊。。。

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧