Передача пути к файлу в Delphi из TOpenDialog в виде строки

Я пытаюсь использовать TOpenDialog, чтобы передать путь к выбранному файлу в AdoConection и загрузить содержимое файла Excel в таблицу. В настоящее время я пытаюсь выполнить приведенный ниже код, но последняя часть кода не подключается к Excel, возвращая ошибку:[dcc32 Error] sample_map.pas (80): E2010 Несовместимые типы: 'string' и 'TOpenDialog'

procedure TForm1.Button1Click(Sender: TObject);
var
  openDialog : TOpenDialog;    // Open dialog variable
  strConn : WideString; // Declare wide string for the connection

begin
  // Create the open dialog object - assign to our open dialog variable
  openDialog := TOpenDialog.Create(self);

  // Set up the starting directory to be the current one
  openDialog.InitialDir := GetCurrentDir;

  // Only allow existing files to be selected
  openDialog.Options := [ofFileMustExist];

  // Allow only .dpr and .pas files to be selected
  openDialog.Filter :=
    'Excel 2003 and older|*.xls|Excel 2007 and older|*.xlsx';

  // Select pascal files as the starting filter type
  openDialog.FilterIndex := 2;

  // Display the open file dialog
  if openDialog.Execute
  then ShowMessage('File : '+openDialog.FileName)
  else ShowMessage('Open file was cancelled');

  // Free up the dialog
  openDialog.Free;

  // Connect the Excel file
    strConn:='Provider=Microsoft.Jet.OLEDB.4.0;' +
                 'Data Source=' + openDialog + ';' +
                 'Extended Properties=Excel 8.0;';
        AdoConnection1.Connected:=False;
        AdoConnection1.ConnectionString:=strConn;
end;

2 ответа

Решение

openDialog является экземпляром файлового диалога Это не строка. Вам нужно прочитать FileName Свойство объекта диалога файла, как это:

openDialog.FileName

На самом деле вы уже используете это в одном из ваших ShowMessage звонки.

Убедитесь, что вы прочитали это свойство перед вызовом Free, ошибка присутствует в коде в вопросе.

На самом деле вам нужно привыкнуть использовать try/finally защищать ресурсы. Каждый раз, когда вы создаете экземпляр класса, вам нужно убедиться, что он будет уничтожен даже в случае исключения. В вашем коде вы должны написать это так:

openDialog := TOpenDialog.Create(self);
try
  .... // use openDialog to let user choose file:
  strConn := 'Provider=Microsoft.Jet.OLEDB.4.0;' +
             'Data Source=' + openDialog.FileName + ';' +
             'Extended Properties=Excel 8.0;';
finally
  openDialog.Free; // executes no matter what, even if exception raised, etc.
end;

Я также не думаю, что вам нужно использовать WideString Вот. Если вы используете Unicode Delphi, то вы можете использовать нативный string тип, который является псевдонимом для UnicodeString, Если ваш Delphi является pre-Unicode, то вы также можете безопасно использовать stringпсевдоним для AnsiString в таком случае. Используемые вами литералы - ASCII. Диалоговое окно файла является элементом управления ANSI и так openDialog.FileName тоже ANSI. Ничего не получится с помощью WideString,

Наконец, вы смешиваете все в одной функции, код для выбора имени файла и код для работы с подключением к базе данных. Лучше разделять проблемы. Создайте метод, который просто возвращает имя файла, полученное путем выбора пользователя в диалоговом окне. И добавьте метод для работы с подключением к базе данных, которому в качестве параметра передается имя файла.

Вам нужно получить OpenDialog.FileName до освобождения диалога:

OpenDialog := TOpenDialog.Create(nil);
try
  // Set up the OpenDialog as before

  // Display the open file dialog
  if openDialog.Execute then
  begin
    strConn := 'Provider=Microsoft.Jet.OLEDB.4.0;' +
               'Data Source=' + openDialog.FileName + ';' +
               'Extended Properties=Excel 8.0;';
    // Connect the Excel file
    AdoConnection1.Connected:=False;
    AdoConnection1.ConnectionString:=strConn;
  else 
    ShowMessage('Open file was cancelled');
finally
  // Free up the dialog
  openDialog.Free;
end;

Конечно, ты слишком много работаешь. Dialogs Устройство имеет гораздо более простой способ сделать это с помощью PromptForFilename функция, которая устраняет необходимость полностью создавать и освобождать диалог:

var
  FileName: string;
begin

  FileName := '';
  if PromptForFileName(FileName,                          // Chosen filename holder
                      'Excel 2003 and older|*.xls|Excel 2007 and older|*.xlsx';  // Filter(s) (optional)
                      '.xlsx',                            // Default extension (opt)
                      'Choose file',                     // Dialog title (opt)
                      GetCurrentDir,                     // Initial dir (opt)
                      False) then                        // Is it a save dlg? (opt)
  begin
    strConn := 'Provider=Microsoft.Jet.OLEDB.4.0;' +
               'Data Source=' + FileName + ';' +
               'Extended Properties=Excel 8.0;';
    // Connect the Excel file
    AdoConnection1.Connected:=False;
    AdoConnection1.ConnectionString:=strConn;
  end
  else
    ShowMessage('Dialog cancelled.');
end;

Как примечание, если вы не знаете: вы можете выбрать все файлы Excel (оба .xls а также .xlsx) с одним фильтром, если вы вводите его как .xls*, как в Excel Files|*.xls*,

И, как говорит Дэвид, лучшим способом было бы разделить код, который получает имя файла, и код, который выполняет соединение, как отдельные функции. Вызовите первое, чтобы получить имя файла, а затем передайте это имя второму, чтобы фактически выполнить соединение, если имя файла выбрано.

Другие вопросы по тегам