0

I have the following function:

Public Function OleDBCSVToDataTable(directory As String, tableName As String, fileName As String, Optional start As Long = 0) As DataTable
    Dim CnStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & directory & ";Extended Properties='Excel 8.0;HDR=YES'"
    Dim dt As DataTable = GetTableSchema(tableName)
    Using Adp As New OleDbDataAdapter("select * from [" & fileName & "]", CnStr)
        Adp.Fill(start, 1000, dt)
    End Using

    Return dt
End Function

The function is designed to read a CSV into a data table using OLEDB for import into SQL, however I am receiving this error:

"The Microsoft Access database engine cannot open or write to the file 'C:\TEST'. It is already opened exclusively by another user, or you need permission to view and write its data."

I have attempted this solution. All permissions have been granted (permissions are Full Control across users):

enter image description here

I have seen this solution as well, however, the proposed options other than OLEDB are solutions that don't seem to work with CSV. Besides, I imagine there are native libraries.

I am open to suggestions for better ways to accomplish this, however, based on requirements - large CSVs, data validation - this appears to be the best, assuming I am able to get it working.

Ken White
  • 123,280
  • 14
  • 225
  • 444
user
  • 1,261
  • 2
  • 21
  • 43
  • 2
    If you are using files that can be read by the Jet engine then I would recommend using that rather than ACE, because Jet is basically part of Windows while ACE requires either Office to be installed or a standalone installation. – jmcilhinney Jun 18 '18 at 02:19
  • You would normally only specify that the file type is Excel if it is an Excel-specific type. Check out [connectionstrings.com](https://www.connectionstrings.com/textfile/) for the usual way to connect to a text file. – jmcilhinney Jun 18 '18 at 02:20
  • Are you sure you don't already have the file open in Excel or elsewhere? – jmcilhinney Jun 18 '18 at 02:21
  • You can also use a `TextFieldParser` to read a CSV file and populate the `DataTable` yourself. In some cases, this can be desirable or even required if ADO.NET doesn't read the data as the data types you want. – jmcilhinney Jun 18 '18 at 02:23
  • You are a saint. Changing the connection string worked. It is now: Dim CnStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & directory & ";Extended Properties=""text;HDR=No;FMT=Delimited"";" I will look into TextFieldParser because there is data validation required. Thanks again. – user Jun 18 '18 at 02:28

1 Answers1

0

How about importing the CSV file into a DataGridView, and then exporting from that object into MS Access?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Globalization;
using System.Configuration;
using System.Data.OleDb;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

         public void button1_Click(object sender, EventArgs e)
         {
         string delimiter = ",";
         string tablename = "medTable";
         DataSet dataset = new DataSet();
         OpenFileDialog openFileDialog1 = new OpenFileDialog();
         openFileDialog1.Filter = "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*";
         openFileDialog1.FilterIndex = 1;
         if (openFileDialog1.ShowDialog() == DialogResult.OK)
         {
         if (MessageBox.Show("Are you sure you want to import the data from \n " + openFileDialog1.FileName + "?", "Are you sure?", MessageBoxButtons.YesNo) == DialogResult.Yes)
         {
         filename = openFileDialog1.FileName;
         StreamReader sr = new StreamReader(filename);
         string csv = File.ReadAllText(openFileDialog1.FileName);
         dataset.Tables.Add(tablename);
         dataset.Tables[tablename].Columns.Add("Order ID");
         dataset.Tables[tablename].Columns.Add("Product");
         dataset.Tables[tablename].Columns.Add("Unit Price");
         dataset.Tables[tablename].Columns.Add("Quantity");
         dataset.Tables[tablename].Columns.Add("Discount");

         string allData = sr.ReadToEnd();
         string[] rows = allData.Split("\r".ToCharArray());

         foreach (string r in rows)
         {
         string[] items = r.Split(delimiter.ToCharArray());
         dataset.Tables[tablename].Rows.Add(items);
         }
         this.dataGridView1.DataSource = dataset.Tables[0].DefaultView;
         MessageBox.Show(filename + " was successfully imported. \n Please review all data before sending it to the database.", "Success!", MessageBoxButtons.OK);
         }
         else
         {
         this.Close();
         }
         }
         }

         public string filename { get; set; }


         private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
         {

         }

         private void Import_Load(object sender, EventArgs e)
         {

         }

         private void button4_Click(object sender, EventArgs e)
         {
         Application.Exit();

         }

         private void button2_Click(object sender, EventArgs e)
         {
         this.Close();
         }

         private void button3_Click(object sender, EventArgs e)

         //remove the semicolon, and add brackets below after line
         { 
         //create the connection string
             string connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Users\\Ryan\\Desktop\\Coding\\Microsoft Access\\Northwind_2012.mdb";

             //create the database query
         string query = "SELECT * FROM [OrderDetailsTest]";

             //create an OleDbDataAdapter to execute the query
         OleDbDataAdapter dAdapter = new OleDbDataAdapter(query, connString);

             //create a command builder
         OleDbCommandBuilder cBuilder = new OleDbCommandBuilder(dAdapter);

             //create a DataTable to hold the query results
         DataTable dTable = new DataTable();

             //fill the DataTable
         dAdapter.Fill(dTable);

             //the DataGridView
         DataGridView dataGridView1 = new DataGridView();

             //BindingSource to sync DataTable and DataGridView
         BindingSource bSource = new BindingSource();

             //set the BindingSource DataSource
         bSource.DataSource = dTable;

             //set the DataGridView DataSource
         dataGridView1.DataSource = bSource;

             // An update function to get the changes back into the database.
         dAdapter.Update(dTable);
         }
    }
 }

enter image description here

ASH
  • 20,759
  • 19
  • 87
  • 200