0

I have created a WPF application that has a graphical user interface that allows users to upload Excel files. These files are supposed to be stored in a designated SQL Server database. I would like each file to be stored as its own table and for the columns to match up with the columns in the file. However, the files aren't even saving to the database. The error messages are working. It tells me that there is no data in the worksheet in the file or the worksheet can't be located, but I know that the file that I am uploading has data and a worksheet in it.

To Select the File -- This part works. I am able to select file(s) in the GUI.

 private void Button_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog() { Multiselect = true };
            bool? response = openFileDialog.ShowDialog();
            if (response == true)
            {
                //Get selected files
                string[] files = openFileDialog.FileNames;
                UploadFiles(files);
            }
        }

To Upload the File -- Not uploading into SQL

private void UploadFiles(string[] files)
        {
            //Iterate and add all selected files to upload
            foreach (string filePath in files)
            {
                string filename = System.IO.Path.GetFileName(filePath);
                FileInfo fileInfo = new FileInfo(filePath);

                // Read Excel data into a DataTable
                DataTable excelData = ReadExcelFile(filePath);

                if (excelData != null)
                {
                    // Get the table name from the file name or any other logic you prefer
                    string tableName = Path.GetFileNameWithoutExtension(filePath);

                    // Create the table in the SQL Server database
                    CreateTable(tableName, excelData);

                    UploadingFilesList.Items.Add(new fileDetail()
                    {
                        FileName = filename,

                        // To convert bytes to Mb
                        FileSize = string.Format("{0} {1}", (fileInfo.Length / 1.049e+6).ToString("0.0"), "Mb"),
                        UploadProgress = 100
                    });

                    MessageBox.Show("File uploaded and stored in the database.");
                }
                else
                {
                    MessageBox.Show("Unable to read Excel file.");
                }
            }
        }

Read the File -- Not acknowledging that there is data or a worksheet

private DataTable ReadExcelFile(string filePath)
        {
            try
            {
                using (var package = new ExcelPackage(new FileInfo(filePath)))
                {
                    ExcelWorksheet worksheet = package.Workbook.Worksheets[1];
                    ExcelRangeBase range = worksheet.Cells[worksheet.Dimension.Address];

                    DataTable dataTable = new DataTable();

                    foreach (var cell in range)
                    {
                        if (cell.Start.Row == 1)
                        {
                            dataTable.Columns.Add(cell.Text);
                        }
                        else
                        {
                            DataRow dataRow = dataTable.NewRow();
                            for (int col = 1; col <= range.Columns; col++)
                            {
                                dataRow[col - 1] = worksheet.Cells[cell.Start.Row, col].Value;
                            }
                            dataTable.Rows.Add(dataRow);
                        }
                    }

                    return dataTable;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error occurred while reading Excel file: " + ex.Message);
                return null;
            }
        }

Create the Table -- Not creating tables

 private void CreateTable(string tableName, DataTable tableData)
        {
            string connectionString = "Connection"; //I have my real connection in the code

            try
            {
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    connection.Open();

                    // Create the SQL CREATE TABLE statement
                    string createTableQuery = "CREATE TABLE " + tableName + " (";

                    foreach (DataColumn column in tableData.Columns)
                    {
                        createTableQuery += "[" + column.ColumnName + "] VARCHAR(MAX), ";
                    }

                    createTableQuery = createTableQuery.TrimEnd(',', ' ') + ")";

                    using (SqlCommand command = new SqlCommand(createTableQuery, connection))
                    {
                        command.ExecuteNonQuery();
                    }

                    // Bulk insert data into the newly created table
                    using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
                    {
                        bulkCopy.DestinationTableName = tableName;
                        bulkCopy.WriteToServer(tableData);
                    }

                    connection.Close();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error occurred while creating table and storing data: " + ex.Message);
            }
        }
    }
}

UPDATE I have added the following to my code to run diagnostics to see where the error occurs:

using System.Diagnostics;

catch (Exception ex)
            {
                // Log the error to the Output window in Visual Studio
                Debug.WriteLine("Error occurred while reading Excel file: " + ex.Message);
                return null;
            }

The output is as follows:

"Exception thrown: 'System.IndexOutOfRangeException' in EPPlus.dll Error occurred while reading Excel file: Worksheet position out of range."

  • That "**Create the Table**" looks *dangerously* open to SQL injection attacks. Also why does every column get defined as a `varchar(MAX)`? – Thom A Jul 18 '23 at 13:48
  • Does this answer your question ? [creating-a-sql-server-table-from-a-c-sharp-datatable](https://stackoverflow.com/questions/1348712/creating-a-sql-server-table-from-a-c-sharp-datatable) – jeb Jul 18 '23 at 14:08
  • Are you getting any errors at all? We can't read over your shoulder to see what's on your screen, so you'll need to [Edit](https://stackoverflow.com/posts/76713457/edit) your question to include the exact text of any error messages (i.e.: **not** as screen shots). I imagine things like `CREATE TABLE Monthly Reports for June ( .... );` wouldn't fly with SQL Server. – AlwaysLearning Jul 18 '23 at 21:56
  • Have you debugged your code? – EspressoBeans Jul 19 '23 at 16:56
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Jul 20 '23 at 11:04
  • I tried to define each column individually as they correspond with the data, but that didn't work either. I have debugged my code and the error that I receive is "Worksheet position out of range" but there is only one worksheet in the file and I have set it to 1 and that didn't work either. – appdevlaur Jul 20 '23 at 15:11
  • I added an update that shows the diagnostics ran on the code and the outputted error. I hope this clears everything up. – appdevlaur Jul 20 '23 at 15:29
  • @appdevlaur did you check the resulting SQL query? It's certainly wrong and would throw an error if you tried to execute id directly, eg in SSMS. Tables aren't files either. Creating one table per file is a *very* bad idea. Create a table yourself, with proper columns and indexes and a `FileName` column, then insert data for all files there. – Panagiotis Kanavos Jul 20 '23 at 15:30
  • The error you posted doesn't have anything to do with tables, it's thrown when you try to process the Excel files because the wrong indexes are used. Did you copy the code [from here](https://stackoverflow.com/a/69090027/134204)? – Panagiotis Kanavos Jul 20 '23 at 15:34
  • Here is the request from the department --> "We receive a monthly spreadsheet from that list oil and gas royalties. They send the excel spreadsheet and add new data every month but it just continues on the same spreadsheet so you can imagine that this spreadsheet has many rows (8,000 I believe). There are also corrections made to the data but that is not identified in the report that is sent. I would enjoy getting your feedback on whether there is a database program that could help with organizing this data." Would this meet the requirements asked? – appdevlaur Jul 20 '23 at 15:45
  • 8K rows is nothing. Excel can store 1M rows per sheet and even 1M rows is not a lot of data for a database. I'd load the entire file into a single staging table, compare it with the previous data using the columns that count as keys, and insert the new rows to the final table – Panagiotis Kanavos Jul 20 '23 at 15:47
  • Okay! I will try that. Thank you so much. – appdevlaur Jul 20 '23 at 15:49
  • Right now I'm dealing with 100s of badly formed Excel files spread around various folders by company. I load each company into a separate *staging* table, because each one uses a different format, with the file name and row in an extra field. – Panagiotis Kanavos Jul 20 '23 at 15:50

1 Answers1

0

The exception is thrown by the attempt to generate a DataTable from EPPlus. EPPlus has multiple ToDataTable methods that can be used to create or fill a DataTable with data from a specific range.

The ReadExcelFile method can be simplified to this:

private DataTable ReadExcelFile(string filePath)
{
    using var package = new ExcelPackage(new FileInfo(filePath));
    var sheet = package.Workbook.Worksheets[1];
    var range = worksheet.Cells[worksheet.Dimension.Address];
 
    var dataTable=range.ToDataTable();   
    return dataTable
}

The method's behavior can be customized through the ToDataTableOptions parameter

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236