Very good community! I had already experienced the following problem before when I made modifications (UPDATES) to the excel sheet, but I always found a solution... but... not now... and the funniest thing that I am following to the letter the steps that microsoft mentions on its official page (it is in english): https://support.microsoft.com/en-us/kb/316934
With ADO.NET, you can insert and update records in a workbook in one of three ways: Directly run a command to insert or update records one at a time. To do this, you can create an OLEDbCommand object on your connection and set its CommandText property to a valid command to insert records
INSERT INTO [Sheet1$] (F1, F2) values ('111', 'ABC')
or a command to update records
UPDATE [Sheet1$] SET F2 = 'XYZ' WHERE F1 = '111'
and then call the ExecuteNonQuery method.
In my program I have functions and methods that collect the sheet depending on the column that is passed as a parameter, and functions that return the exact position of an empty cell or with errors (A1, B2, C15...) I have compared hundreds of Sometimes if the functions are returning what is desired, and well yes... they are all working fine... then the problem would be the substitution function itself...
Protected Friend Sub reemplazarDato(ByVal DColumn As String, ByVal headerCell As String, ByVal cell As String, ByVal dato As String)
Dim hoja As String = obtenerHojaActual(DColumn)
Dim comando As New OleDbCommand
comando.Connection = conexion
comando.CommandText = "UPDATE [" & hoja & "$] SET [" & cell & "]=@dato WHERE [" & headerCell & "]=@DColumn"
comando.Parameters.Add("@dato", OleDbType.Date).Value = dato
comando.Parameters.Add("@DColumn", OleDbType.VarChar).Value = DColumn
MsgBox(comando.CommandText)
MsgBox("Dato nuevo: " + comando.Parameters(0).Value + " en la columna: " + comando.Parameters(1).Value)
conexion.Open()
Try
comando.ExecuteNonQuery()
Catch ex As Exception
cajaMensaje("Error inesperado", ex.Message, My.Resources._error).ShowDialog()
End Try
conexion.Close()
comando.Dispose()
End Sub
These message boxes are inserted to verify that the data is being inserted correctly and the query is being written correctly. I am going to cite an example that I am trying now... I am trying to change the value of cell C2 of this excel sheet:
The commandText that prints the program's mssgbox...
Note the similarity to the microsoft one: UPDATE [Sheet1$] SET F2 = 'XYZ' WHERE F1 = '111'
Could it be that the parameters are not storing the values? Well, they do.
And before they answer me "you have to remove the brackets from the values that represent columns", well no, I have already removed them and it doesn't work the same (besides, the same page suggests that they be used when marking columns) , I also tried making a regular query with concatenations and the same, nothing (also the same page suggests that queries with parameters be used when writing them)...
What could this strange problem be?
UPDATE
Reading on the web about the problem, I found something else; You need to disable the HDR property to be able to modify a specific cell. Insert a parameter in the String property of the connection to indicate whether it will be activated or deactivated on a certain operation.
Protected Friend Property setConnection(ByVal hdr As String) As String
Set(value As String)
Try
conexion.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & value & ";Extended Properties='Excel 8.0;HDR=" & hdr & ";IMEX=0;TypeGuessRows=0;'"
Catch ex As Exception
cajaMensaje("Error inesperado", ex.Message, My.Resources._error).ShowDialog()
End Try
End Set
Get
Return conexion.ConnectionString
End Get
End Property
I also found that a range should be indicated to modify that cell. I did the following but it didn't work for me (It throws me the same error...) and honestly I don't get to understand that about the range. The method is then as follows:
Protected Friend Sub reemplazarDato(ByVal DColumn As String, ByVal cell As String, ByVal dato As String)
Dim hoja As String = obtenerHojaActual(DColumn)
Dim comando As New OleDbCommand
setConnection("NO") = setRuta
MsgBox(conexion.ConnectionString)
comando.Connection = conexion
comando.CommandText = "UPDATE [" & hoja & "$" & cell & ":" & cell & "] SET [" & cell & "]=@dato"
MsgBox(comando.CommandText)
comando.Parameters.Add("@dato", OleDbType.VarChar, dato.Length).Value = dato
conexion.Open()
Try
comando.ExecuteNonQuery()
Catch ex As Exception
cajaMensaje("Error inesperado", ex.Message, My.Resources._error).ShowDialog()
End Try
conexion.Close()
comando.Dispose()
End Sub
Estuve depurando el código sobre 32 bits, y encontré la causa del problema.
The links in the question are very helpful, especially How To Use ADO.NET to Retrieve and Modify Records in an Excel Workbook With Visual Basic .NET
To do it in an Excel
UPDATE
sheet , we have two options: with or without header.1. With header or also called record update
The header is the name of the columns, and when it is present it must be indicated in the connection string, through the property
HDR=YES
:In this way we can make the statement
UPDATE
as we do for any query to a database:UPDATE Tabla SET campo1 = valor1, campo2 = valor2, ...
For the question code:
The column
C
has the nameDate
, which is a reserved word, and therefore the use of brackets is essential,[
and]
insteadName
we see that it does not need them.Interestingly it works
Excel 8.0
for the motorACE 12.0
2. No header or also called individual cell update
This time, in the connection string we need to set the property
HDR=NO
:IMEX
andTypeGuessRows
they cannot be used here because they depend on rows having column headers, i.e. they are only used whenHDR=YES
Here the sentence
UPDATE
, requires some rules to follow:Specify the range of cells that will be updated.
Instead of column names, the letter F followed by an ordinal is used, indicating the column.
For example, to change the header:
by the name of the cells:
Must do:
For the question code:
I used
DateSerial
, to avoid problems with date formatting.The range of cells must always be indicated, even if only one is updated.