How to INSERT into table using Entity Data Model (EDMX) - frameworks

I am trying to write a button handler in VB.NET that will read rows from a gridview and write them to a DB if a checkbox is checked.
I setup this application to use EntityDataSource and added my .edmx file to a DAL folder. I have the button method written but I do not know enough about EF to know how to handle the data the data from the gridview. Here is my btn_click method:
Private Sub btnGetChecks_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnGetChecks.Click
'********************************************
'* gets status of checkbox and writes to db *
'********************************************
Dim row As GridViewRow
Label6.Text = ""
For Each row In DvsGridView.Rows
Dim RowCheckBox As CheckBox = CType(row.FindControl("chkStatus"), CheckBox)
If RowCheckBox.Checked Then
Label6.Text += row.Cells(5).Text & " Checked "
' Need to write checked data to the db
' ******* WHAT GOES HERE? *******
Else
Label6.Text += row.Cells(5).Text & " Unchecked "
End If
Next
End Sub
I am fairly new to EDMX but understand VB.net. Any direction would be greatly appreciated.

Check this sample code and modify this to match your entities and objects
Using db As New DBEntities()
'set values here
Dim x As New TableNameE()
x.col1 = "value1"
x.col2 = "value2"
db.AddToTableNameE(x)
db.SaveChanges()
End Using

Thanks to #rs., I was able to figure out my issues. Referring to the accepted answer, for those wondering what .AddToTableNameE() should be in your proj, it's just going to be .Add(x). It's also somewhat a performance hit using .SaveChanges() for every row, you should create a Dim List(Of TableNameE()) and add the "x" to the list, then use .AddRange() like this:
//creating a data access class is one way to connect to your db by passing in db path
Dim context As New Namespace.YourContext(New DataAccessClass() With {.Path = aBrowsedForSDFFileTextBoxMaybe.Text})
Dim listOfTableObjects As List(Of Namespace.TableObject) = New List(Of Namespace.TableObject)
For n = 1 To SomethingRelatedToRows
Dim tableObject As New Namespace.TableObject() With {
.entityProp1 = TableObject(n).entityProp1,
.entityProp2 = TableObject(n).entityProp2,
.entityProp3 = TableObject(n).entityProp3,
.entityProp4 = TableObject(n).entityProp4,
.entityProp5 = TableObject(n).entityProp5,
.entityProp6 = TableObject(n).entityProp6
}
listOfTableObjects.Add(tableObject)
Next n
//.TableObjects being the DbSet from the ...Context.vb file
context.TableObjects.AddRange(listOfTableObjects)
context.SaveChanges()

Related

XLSX file via OpenXml SDK Both Valid and Invalid

I have a program which exports a System.Data.DataTable to an XLSX / OpenXml Spreadsheet. Finally have it mostly working. However when opening the Spreadsheet in Excel, Excel complains about the file being invalid, and needing repair, giving this message...
We found a problem with some content in . Do you want us to
try to recover as much as we can? If you trust the source of the
workbook, clik Yes.
If I click Yes, it comes back with this message...
Clicking the log file and opening that, just shows this...
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<recoveryLog xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<logFileName>error268360_01.xml</logFileName>
<summary>Errors were detected in file 'C:\Users\aabdi\AppData\Local\Temp\data.20190814.152538.xlsx'</summary>
<repairedRecords>
<repairedRecord>Repaired Records: Cell information from /xl/worksheets/sheet1.xml part</repairedRecord>
</repairedRecords>
</recoveryLog>
Obviously, we don't want to deploy this into a production environment like this. So I've been trying to figure out how to fix this. I threw together a quick little sample to validate the XML and show the errors, based on this link from MSDN. But when I run the program and load the exact same XLSX document that Excel complains about, the Validator comes back saying that the file is perfectly Valid. So I'm not sure where else to go from there.
Any better tools for trying to validate my XLSX XML? Following is the complete code I'm using to generate the XLSX file. (Yes, it's in VB.NET, it's a legacy app.)
If I comment out the line in the For Each dr As DataRow loop, then the XLSX file opens fine in Excel, (just without any data). So it's something with the individual cells, but I'm not really DOING much with them. Setting a value and data type, and that's it.
I also tried replacing the For Each loop in ConstructDataRow with the following, but it still outputs the same "bad" XML...
rv.Append(
(From dc In dr.Table.Columns
Select ConstructCell(
NVL(dr(dc.Ordinal), String.Empty),
MapSystemTypeToCellType(dc.DataType)
)
).ToArray()
)
Also tried replacing the call to Append with AppendChild for each cell too, but that didn't help either.
The zipped up XLSX file (erroring, with dummy data) is available here:
https://drive.google.com/open?id=1KVVWEqH7VHMxwbRA-Pn807SXHZ32oJWR
Full DataTable to Excel XLSX Code
#Region " ToExcel "
<Extension>
Public Function ToExcel(ByVal target As DataTable) As Attachment
Dim filename = Path.GetTempFileName()
Using doc As SpreadsheetDocument = SpreadsheetDocument.Create(filename, DocumentFormat.OpenXml.SpreadsheetDocumentType.Workbook)
Dim data = New SheetData()
Dim wbp = doc.AddWorkbookPart()
wbp.Workbook = New Workbook()
Dim wsp = wbp.AddNewPart(Of WorksheetPart)()
wsp.Worksheet = New Worksheet(data)
Dim sheets = wbp.Workbook.AppendChild(New Sheets())
Dim sheet = New Sheet() With {.Id = wbp.GetIdOfPart(wsp), .SheetId = 1, .Name = "Data"}
sheets.Append(sheet)
data.AppendChild(ConstructHeaderRow(target))
For Each dr As DataRow In target.Rows
data.AppendChild(ConstructDataRow(dr)) '// THIS LINE YIELDS THE BAD PARTS
Next
wbp.Workbook.Save()
End Using
Dim attachmentname As String = Path.Combine(Path.GetDirectoryName(filename), $"data.{Now.ToString("yyyyMMdd.HHmmss")}.xlsx")
File.Move(filename, attachmentname)
Return New Attachment(attachmentname, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
End Function
Private Function ConstructHeaderRow(dt As DataTable) As Row
Dim rv = New Row()
For Each dc As DataColumn In dt.Columns
rv.Append(ConstructCell(dc.ColumnName, CellValues.String))
Next
Return rv
End Function
Private Function ConstructDataRow(dr As DataRow) As Row
Dim rv = New Row()
For Each dc As DataColumn In dr.Table.Columns
rv.Append(ConstructCell(NVL(dr(dc.Ordinal), String.Empty), MapSystemTypeToCellType(dc.DataType)))
Next
Return rv
End Function
Private Function ConstructCell(value As String, datatype As CellValues) As Cell
Return New Cell() With {
.CellValue = New CellValue(value),
.DataType = datatype
}
End Function
Private Function MapSystemTypeToCellType(t As System.Type) As CellValues
Dim rv As CellValues
Select Case True
Case t Is GetType(String)
rv = CellValues.String
Case t Is GetType(Date)
rv = CellValues.Date
Case t Is GetType(Boolean)
rv = CellValues.Boolean
Case IsNumericType(t)
rv = CellValues.Number
Case Else
rv = CellValues.String
End Select
Return rv
End Function
#End Region
For anyone else coming in and finding this, I finally tracked this down to the Cell.DataType
Setting a value of CellValues.Date will cause Excel to want to "fix" the document.
(apparently for dates, the DataType should be NULL, and Date was only used in Office 2010).
Also, if you specify a DataType of CellValues.Boolean, then the CellValue needs to be either 0 or 1. "true" / "false" will also cause Excel to want to "fix" your spreadsheet.
Also, Microsoft has a better validator tool already built for download here:
https://www.microsoft.com/en-us/download/details.aspx?id=30425

Programmatically created form with name conflict

I'm creating in Excel VBA a form using code. The following code snippet presents a problem in which the form is somehow created with the name already correctly set and then afterwards, in the only place where I set the said variable, it raises an issue saying that there is a form with that name (the variable in case).
Here is my code:
Dim frmName As String
frmName = "frm_" & Replace(CStr(Nome_do_formulario), " ", "")
Set myForm = ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_MSForm)
With myForm
.Properties("Caption") = Nome_do_formulario
.Properties("Width") = 300
.Properties("Height") = 270
.Properties("Name") = frmName
End With
To be clear, the error is that when it reaches the line:
Set myForm = ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_MSForm)
Somehow it already creates a form with name that's set after at the with statement:
With myForm
.Properties("Caption") = Nome_do_formulario
.Properties("Width") = 300
.Properties("Height") = 270
.Properties("Name") = frmName '<- HERE
End With
And then, when it tries to run the with statement it breaks and says that a form with that name already exists.
The whole thing is ran at another module as:
Public Sub Main()
Dim ac As autoCrud
Set ac = New autoCrud
ac.CreateCRUDView
End Sub
The form creation happens inside the ac.CreateCRUDView.
How is it pulling the name variable before it's set and then trying to use it to make another form with the same name?
VBE suffers heavily corruption when it is about UserForms collection in a VBA Project.
Even if you remove explicitly a UserForm from your project, you might get errors creating programatically (and sometimes in the normal way) another with the same name.
Try using this approach:
Dim frmName As String
Dim myForm As VBComponent
frmName = "frm_" & Replace(CStr(Nome_do_formulario), " ", "")
ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_MSForm).Name = frmName
Set myForm = ThisWorkbook.VBProject.VBComponents(frmName)
With myForm
.Properties("Caption") = Nome_do_formulario
.Properties("Width") = 300
.Properties("Height") = 270
End With
Remember, if you delete the newly created userform and run this code with the same Nome_do_formulário value, you'll get an error.

VB Script in Access Variable not found

So I was advised that I could create some copy replace functionality to this form.
Here is my coding attempt in VB:
First I connect to DB using DAO. Then I use a SELECT statement that has been verified to pull the last record inserted into the DB. Then I try to refill the controls with the values from the query but I am getting reference errors.
Private Sub AutoFill_Click()
Dim db As DAO.Database, rs As DAO.Recordset
Dim strSQL As String
Set db = CurrentDb()
strSQL = "SELECT DISTINCTROW TOP 1 CPOrders.Cust, Customer.NAME, CPOrders.CP_Ref, CPOrders.Slsman, CPOrders.Date_opn, CPOrders.CPSmall, CPOrders.InvIssu, CPOrders.InvNo, CPOrders.InvDate, CPOrders.DueDate, CPOrders.ETADate, CPOrders.Closed, CPOrders.BuyerRef, CPOrders.ToCity, CPOrders.ToState, CPOrders.ToCtry, CPOrders.ToPort, CPOrders.Supplier, CPOrders.Origin, CPOrders.Product, CPOrders.GradeType, CPOrders.NoUnits, CPOrders.Pkg, CPOrders.Qty, CPOrders.TotSale, CPOrders.TotCost, CPOrders.GrMargin, CPOrders.[Sale$/Unit], CPOrders.[Cost$/Unit], CPOrders.OceanCost, CPOrders.OceanNotes, CPOrders.BLadingDate, CPOrders.USAPort, CPOrders.FOBCost, CPOrders.FASExportVal, CPOrders.InlandFrt, CPOrders.CommodCode, CPOrders.Notes FROM Customer INNER JOIN CPOrders ON Customer.[CUST_#] = CPOrders.Cust ORDER BY CPOrders.CP_Ref desc;"
Set rs = db.OpenRecordset(strSQL, dbOpenDynaset, dbReadOnly)
rs.MoveFirst
CP_Ref.ControlSource = rs!CP_Ref
Slsman.ControlSource = rs!Slsman
CPSmall.ControlSource = rs!CPSmall
InvIssu.ControlSource = rs!InvIssu
InvDate.ControlSource = rs!InvDate
DueDate.ControlSource = rs!DueDate
Closed.ControlSource = rs!Closed
rs.Close
db.Close
The control source reference picks up and autocompletes the word.
I would think that as it stands. although i'm not filling all the values with records from my SELECT statement that it would populate but instead i get things like #NAME? where the values should be. I also get a break in my code and it says "Invalid use of null"
Why? I appreciate your guys input and I can provider screenshots if necessary. I think this is involving the reference tie, but I'm not sure. Any help is much appreciated.
You are using the field names from the SELECT statement as if they were variables.
CP_Ref.ControlSource = rs("CP_Ref")
Slsman.ControlSource = rs("Slsman")
CPSmall.ControlSource = rs("CPSmall")
InvIssu.ControlSource = rs("InvIssu")
InvDate.ControlSource = rs("InvDate")
DueDate.ControlSource = rs("DueDate")
Closed.ControlSource = rs("Closed")
When you have that worked out, tackle the "Invalid use of null" problem by first identifying any fields that could potentially be NULL and using something like
SELECT Iif(IsNull([InvDate]), '', [InvDate]) As [InvDate], ...
in the SELECT statement to pass across a minimum of an empty string rather than a NULL value.

Access VBA visible control form from another form

I have a table and form setup to control another form in my database.
I'm wanting to make a code that will take the title from my field and add it to my code as a variable to change the visibility options of my other form.
my form is set with all the of the names to all objects on the form I want to control.
LSE_FORM_ADMIN = The table with all the LSE_FORM_ALL names in it.
Table is setup with 3 columns key, names and a checkbox which I put into a form to make a continuous list.
here is my code on the form, but I keep getting and runtime 424: object required error:
Private Sub Form_Current()
Dim VARSET As Object
Dim VAR As String
VARSET = DLookup("TITLE", Table!LSE_FORM_ADMIN, "") 'keep getting error here
VAR = VARSET
If Me!CB = "-1" Then
Form_LSE_FORM_ALL!VAR.Visible = True
Else
Form_LSE_FORM_ALL!VAR.Visible = False
End If
End Sub
can someone help me fix this code so that it will grab the title field data and make it a variable to add to the rest of the code?
It's difficult to see exactly what you are trying to achieve, but your problems stem from using the variant variable type when you should be using an explicit Form or Control type. Using your last example.
RSTT.Visible = True 'getting Run-time error '424': object required
This is because you have declared RSTT as a variant. The line
RSTT = "Form_LSE_FORM_ALL" & "!" & (RST)
results in the variable RSTT containing a string, which does not have a property ".Visible"
Set DB = CurrentDb
Set RS = DB.OpenRecordset("LSE_FORM_ADMIN")
These lines are redundant as you have the values that you need available on the form fields which are already bound to the table LSE_FORM_ADMIN.
As far as I understand, you have a continuous form (ADMIN?) bound to the table LSE_FORM_Admin. As you step through the records on this form, you want code to be fired which takes the value of the TITLE field/control and use it to set a control with the same name, on a separate form, Form_LSE_FORM_ALL, to be (in)visible, dependent on the value of the checkbox control name CB on the ADMIN form?
If you want the ADMIN form to make the changes "live" to the ALL form, you should consider using an event of the CB checkbox control. Using the current event of the form means that the changes you make will not be reflected in the ALL form until you step out of the record you have just edited, then back in, to fire the form's Current event on that record.
Example using AfterUpdate event of CB checkbox
Private Sub CB_AfterUpdate()
Dim strRST As String
Dim frmTarget as Form
Dim ctlRSTT As Control
Set strRST = Me!TITLE
Set frmTarget = Forms("Form_LSE_FORM_ALL")
Set ctlRSTT = frmTarget.Controls(strRST)
ctlRSTT.Visible = Me!CB 'getting Run-time error '424': object required
End Sub
really not sure how to do the syntax when doing a recordset to a table from the form, need some help with that.
here is my code and attempt at the record set:
Private Sub Form_Current()
Dim DB As Database
Dim RS As Recordset
Dim RST As String
Set DB = CurrentDb
Set RS = DB.OpenRecordset("LSE_FORM_ADMIN")
Set RST = RS 'GETTING OBJECT REQUIRED ERROR ON "RST ="
Do Until RS.EOF
RST = Me!TITLE
RS.MoveNext
Loop
If Me!CB = "-1" Then
Form_LSE_FORM_ALL!RS.Visible = True
Else
Form_LSE_FORM_ALL!RS.Visible = False
End If
End Sub
I think I know what you are trying to do, but your descriptions / references are not matching up. Please look at the following comments and clarify:
1. You say "...make a code that will take the title from my field and ..." but your code is taking "Me.Title", "ME" is a reference to the Form - not a field.
2. Your code is in the "Form_Current" event, which means it will fire for every record you process. That will work, but I think you want to do this code only once to be more efficient.
3. You have no provision for processing more than one field. I think you need to loop through all fields in your table, setting visible to true or false.
The following is my suggestion, but I will update once you clarify the issues.
Option Compare Database
Option Explicit
Dim DB As DAO.Database
Dim RS As DAO.Recordset
'Dim RST As Variant
'Dim RSTT As Variant
Public Sub FORM_CURRENT()
Set DB = CurrentDb
Set RS = DB.OpenRecordset("LSE_FORM_ADMIN")
Do While Not RS.EOF ' Loop thru all field names for the form
If RS!HideYN = True Then ' Desire to hide the field?
Me(RS!ctlname).Visible = False ' Yes, hide the field.
Else
Me(RS!ctlname).Visible = True ' No, show the field
End If
RS.MoveNext ' Get next field name
Loop
RS.Close
Set RS = Nothing
Set DB = Nothing
'Set RST = Me!Title
'RSTT = "Form_LSE_FORM_ALL" & "!" & (RST)
'If Me!CB = "-1" Then
' RSTT.Visible = True 'getting Run-time error '424': object required
'Else
' RSTT.Visible = False
'End If
End Sub
Final code, thanks to Cheesenbranston.
Private Sub Form_AfterUpdate()
Dim strRST As String
Dim frmTarget As Form
Dim ctlRSTT As Control
strRST = Me!TITLE
Set frmTarget = Forms("LSE_FORM_ALL")
Set ctlRSTT = frmTarget.Controls(strRST)
If Me!CB = "-1" Then
ctlRSTT.Visible = True
Else
ctlRSTT.Visible = False
End If
End Sub
#Cheesenbranston: Your original code was more like a toggle of on and off so if my object was not visible then my trigger checkbox would make it visible when checked, more of a quality of life for my own needs, none the less worked. Also strRST doesn't need SET since its just a String. Thanks again =D very happy day!

on Button press If(No record exist) Then create Else Update

I have an unbound form. On the form i have a save button. As of now when you press the save button it saves the information on the form to a record, but every time you press save it adds a new record instead of updating it. I need it to Update the current record instead of adding a new record. Any ideas is appreciated.
here is my code:
Dim dblocal As DAO.Database
Dim rst As DAO.Recordset
Set dblocal = CurrentDb()
Set rst = dblocal.OpenRecordset("SUBJECT_DATABASE", dbOpenDynaset)
'Prim. ID var.
Dim EvtIDkey As Long
With rst
.AddNew
.Fields("LAST NAME") = Me.LNameTxtB
.Fields("FIRST NAME") = Me.FNameTxtB
.Fields("GENDER") = Me.GenderCboB
.Fields("DOB") = Me.DOBTxtB
'inserts primary id into textB
Me.EvtIDKeyTxtB = .Fields("ID")
.Update
End With
End If
I was thinking to add a if statement with the following conditions:
If EvtIDKeyTxTB is not empty update exist record. However, how do i update an existing record?
If i have the Primary key would i be able to get and update the record that way?