C# 以编程方式将打开窗口中的Excel表保存到文件中

C# 以编程方式将打开窗口中的Excel表保存到文件中,c#,.net,excel,C#,.net,Excel,这就是我需要做的 有一个程序连接到某个服务器,并以每秒大约15-20个条目的速度从该服务器获取数据 就在与服务器建立连接时,一个Excel窗口打开,从服务器获取的所有条目都会动态移动到该Excel表中 但是,所有内容都保留在RAM中,即只有当我们尝试关闭Excel窗口并出现“另存为…”对话框时,才会创建Excel文件本身 正如您可能已经理解的,我不想每次都手动保存文件,因此我需要某种方法以编程方式将Excel表保存在打开的窗口中,并保存到文件中 有办法吗 如果您没有在服务器上运行此操作,并且不介

这就是我需要做的

有一个程序连接到某个服务器,并以每秒大约15-20个条目的速度从该服务器获取数据

就在与服务器建立连接时,一个Excel窗口打开,从服务器获取的所有条目都会动态移动到该Excel表中

但是,所有内容都保留在RAM中,即只有当我们尝试关闭Excel窗口并出现“另存为…”对话框时,才会创建Excel文件本身

正如您可能已经理解的,我不想每次都手动保存文件,因此我需要某种方法以编程方式将Excel表保存在打开的窗口中,并保存到文件中


有办法吗

如果您没有在服务器上运行此操作,并且不介意手动触发Excel保存,那么您可以使用Interop创建连接到Excel实例的内容。以下内容将连接到Excel实例,并返回指定工作簿名称的
Excel.Workbook
对象:

private Excel.Workbook GetWorkbook(string workbookName)
{
    Excel.Window window = null;      // Excel window object from which application is grabbed
    Excel.Application app = null;    // Excel instance from which we get all the open workbooks
    Excel.Workbooks wbs = null;      // List of workbooks
    Excel.Workbook wb = null;        // Workbook to return
    EnumChildCallback cb;            // Callback routine for child window enumeration routine
    List<Process> procs = new List<Process>();           // List of processes

    // Get a full list of all processes that have a name of "excel"

    procs.AddRange(Process.GetProcessesByName("excel"));

    foreach (Process proc in procs)
    {
        // Make sure we have a valid handle for the window

        if ((int)proc.MainWindowHandle > 0)
        {
            // Get the handle of the child window in the current Excel process

            int childWindow = 0;
            cb = new EnumChildCallback(EnumChildProc);
            EnumChildWindows((int)proc.MainWindowHandle, cb, ref childWindow);

            // Make sure we got a valid handle

            if (childWindow > 0)
            {
                // Get the address of the child window so that we can talk to it and
                // get all the workbooks

                const uint OBJID_NATIVEOM = 0xFFFFFFF0;
                Guid IID_IDispatch =
                    new Guid("{00020400-0000-0000-C000-000000000046}");
                int res = AccessibleObjectFromWindow(childWindow, OBJID_NATIVEOM,
                    IID_IDispatch.ToByteArray(), ref window);

                if (res >= 0)
                {
                    app = window.Application;
                    wbs = app.Workbooks;

                    // Loop through all the workbooks within the current Excel window
                    // to see if any match

                    for (int i = 1; i <= wbs.Count; i++)
                    {
                        wb = wbs[i];

                        if (wb.Name == workbookName)
                        {
                            break;
                        }

                        wb = null;
                    }
                }
            }
        }

        // If we've already found our workbook then there's no point in continuing
        // through the remaining processes

        if (wb != null)
        {
            break;
        }
    }

    Release(wbs);
    Release(app);
    Release(window);

    return wb;
}

一旦你有了工作簿,你就可以调用
workbook.SaveAs()
来保存它。

你试过使用EPPlus吗?我简单地看了一下EPPlus,但没有找到任何解决问题的方法。EPPlus是专门为处理Excel表而设计的,而我的问题主要是处理系统中打开的窗口。填充了表的Excel实例是否在服务器上运行?您需要将其作为服务运行,还是手动运行程序来保存Excel工作簿?是否会弹出“另存为…”对话框?我不应该手动触发Excel保存,这应该由程序自动完成。(给定我们希望Excel表格保存到的文件名)@mangusta通过使用
SaveAs()
调用并在其中指定文件名,可以防止“另存为”对话框弹出。看一看。
private delegate bool EnumChildCallback(int hwnd, ref int lParam);

[DllImport("User32.dll")]
private static extern bool EnumChildWindows(int hWndParent, EnumChildCallback lpEnumFunc, ref int lParam);

[DllImport("Oleacc.dll")]
private static extern int AccessibleObjectFromWindow(int hwnd, uint dwObjectID, byte[] riid, ref Excel.Window ptr);

private bool EnumChildProc(int hwndChild, ref int lParam)
{
    // Get the name of the class that owns the passed-in window handle

    StringBuilder buf = new StringBuilder(128);
    GetClassName(hwndChild, buf, 128);

    // If the class name is EXCEL7 then we've got an valid Excel window

    if (buf.ToString() == "EXCEL7")
    {
        lParam = hwndChild;
        return false;
    }

    return true;
}

[DllImport("User32.dll")]
private static extern int GetClassName(int hWnd, StringBuilder lpClassName, int nMaxCount);