none
переоткрыть с сохранением Excel файл

    Вопрос

  • Ребят, есть вопрос (хотя заголовок звучит странно). На данную тему уже есть немало обсуждений, но может быть ситуация здесь проще.

    Работаю в C#, используя Microsoft.Office.Interop.Excel. Создаю excel, записываю в него данные, затем сохраняю и закрываю. А потом, чтобы пользователь не искал его, открываю его с помощью System.Diagnostics.Process.Start().

    Например, на форме есть кнопка save_button, при нажатию на которую и осуществляются все эти процедуры:

    private void save_button_Click(object sender, EventArgs e)            
    {
                string path;
                path = Directory.GetCurrentDirectory();
                Excel.Application app = new Excel.Application();
                app.SheetsInNewWorkbook = 1;
                Excel.Workbook wb = app.Workbooks.Add();
                Excel.Worksheet worksheet = wb.ActiveSheet;
    
                //... здесь записываем данные в файл...
                
                app.DisplayAlerts = false;
                wb.SaveAs(path + @"\file.xlsx");
                wb.Close(true);
                app.Quit();        
     
     System.Diagnostics.Process.Start(Directory.GetCurrentDirectory() + @"\file.xlsx"); // Открываем файл для просмотра
    
    }

    Но!!! Если этот файл будет открыт, и я снова нажму save_button, то вылезет исключение:

    System.Runtime.InteropServices.COMException: "Нет доступа к 'file.xlsx'."

    Как можно сделать так, чтобы программа определяла открыт файл или нет, и если открыт, то закрывала его, сохраняла изменения и снова открывала ??


    Андрей

    3 февраля 2019 г. 10:43

Ответы

  • Для того, чтобы подключиться к уже запущенному экземпляру Excel, используйте Marshal.GetActiveObject:

    Excel.Application app = (Excel.Application) Marshal.GetActiveObject("Excel.Application");
    Если результат null, значит Excel не открыт. В противном случае, проходите по Workbooks и смотрите, есть ли там то, что нужно вам (по свойству Name или Path).  


    3 февраля 2019 г. 17:08

Все ответы

  • Для того, чтобы подключиться к уже запущенному экземпляру Excel, используйте Marshal.GetActiveObject:

    Excel.Application app = (Excel.Application) Marshal.GetActiveObject("Excel.Application");
    Если результат null, значит Excel не открыт. В противном случае, проходите по Workbooks и смотрите, есть ли там то, что нужно вам (по свойству Name или Path).  


    3 февраля 2019 г. 17:08
  • Как можно сделать так, чтобы программа определяла открыт файл или нет, и если открыт, то закрывала его, сохраняла изменения и снова открывала ??

    Перехватить исключение и в обработчике сделать все, что требуется. С конструкцией "try - catch" знакомы?

    Если сообщение помогло Вам, пожалуйста, не забудьте отметить его как ответ данной темы. Удачи в программировании!

    6 февраля 2019 г. 19:21
  • kosuke904, хахаха, как смешно! Ну конечно знаю. Если было бы все так просто, я, наверное, не задавал бы вопросов сюда.

    Андрей

    7 февраля 2019 г. 8:50
  • VadimTagil, Извините за задержку с ответом. Нашел такую конструкцию. Но нужно чуть кода добавить =)

    допустим мы нашли процесс Excel.Application, а как закрыть процесс в котором открыта именно моя книга, к примеру my_file.xlsx ?? там по-любому нужно пробежаться циклом foreach по какой-то коллекции, наверное, и по свойству Name отрубить его. 

    private void save_button_Click(object sender,

    EventArgs e) { try

    { string path; path = Directory.GetCurrentDirectory(); Excel.Application app = new Excel.Application(); app.SheetsInNewWorkbook = 1; Excel.Workbook wb = app.Workbooks.Add(); Excel.Worksheet worksheet = wb.ActiveSheet; //... здесь записываем данные в файл... app.DisplayAlerts = false; wb.SaveAs(path + @"\file.xlsx"); wb.Close(true); app.Quit(); System.Diagnostics.Process.Start(Directory.GetCurrentDirectory() + @"\file.xlsx"); // Открываем файл для просмотра } catch (Exeption) { Excel.Application app = (Excel.Application)Marshal.GetActiveObject("Excel.Application"); // и как остановить процесс, в котором открыта именно моя книга my_file.xlsx?? } }




    Андрей

    7 февраля 2019 г. 9:03
  • Современные версии Excel открывают все документы в одном процессе, если их явно не попросить об обратном. 

    "там по-любому нужно пробежаться циклом foreach по какой-то коллекции, наверное, и по свойству Name отрубить его. "

    Да, я же написал:

    "В противном случае, проходите по Workbooks и смотрите, есть ли там то, что нужно вам (по свойству Name или Path)."

    Name - имя файла, Path - каталог. FullName, вроде, содержит полный путь к файлу.

    7 февраля 2019 г. 9:59
  • с помощью какого метода я должен остановить процесс ? 

    Marshal.ReleaseComObject() -- этот ??

    private void save_button_Click(object sender, 
    EventArgs e)            
    {
    
       try 
       {
                string path;
                path = Directory.GetCurrentDirectory();
                Excel.Application app = new Excel.Application();
                app.SheetsInNewWorkbook = 1;
                Excel.Workbook wb = app.Workbooks.Add();
                Excel.Worksheet worksheet = wb.ActiveSheet;
    
                //... здесь записываем данные в файл...
                
                app.DisplayAlerts = false;
                wb.SaveAs(path + @"\file.xlsx");
                wb.Close(true);
                app.Quit();        
     
                System.Diagnostics.Process.Start(Directory.GetCurrentDirectory() + @"\file.xlsx"); // Открываем файл для просмотра
    
       }
       catch (Exeption)
       {
           Excel.Application app = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
    
           // и как остановить процесс, в котором открыта именно моя книга my_file.xlsx?? 
        
        if (app != null)
        {
          foreach (var wb in app.Workbooks)
          {
             if ((wb as Excel.Workbook).FullName.Equals("Типизация.xlsx"))
                {
                   (wb as Excel.Workbook).Close();
                    Marshal.ReleaseComObject(app);
                    app.Quit();
                 }
          }
    
        }
    
       }
    
    }

    что-то типа такого не хочет работать.


    7 февраля 2019 г. 10:28
  • И не должно. Вызов GetActiveObject должен быть до создания нового экземпляра Excel. Иначе он вернет этот же вами созданный экземпляр...

    Excel.Application app=null;           
    
    try
    {
        app = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
    }
    catch (COMException) { app = null; }
    
    if (app != null)
    {
        foreach (Excel.Workbook x in app.Workbooks)
        {
    	if (x.FullName == path + @"\file.xlsx")
            {
                x.Save();
                x.Close(true);
                break;
            }
        }
    }
    
    app = new Excel.Application();
    
    //работа с Excel...
    
    System.Diagnostics.Process.Start(Directory.GetCurrentDirectory() + @"\file.xlsx");

    7 февраля 2019 г. 10:52