I am having trouble inserting a DateTime.toIso8601String() into a SQLite (SQFlite) database in Dart. The issue I am having is with a property_model class, who's only job is to interact with the database and hold data. I have an almost identical address_model class that works how I expect it, but I am having trouble with the property_model. Whenever I try to call the Property.insert() method, I get this error:
E/flutter: [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: Invalid argument: Instance of 'DateTime'
I don't have this issue with the very similar Address class though, and I am pretty stumped. Here are the property_model, address_model, and database files I am using (the database.dart file is a singleton that I use throughout the application).
property_model.dart
import 'package:flutter/material.dart';
import 'package:sqflite/sqflite.dart';
import 'package:villadex/model/database.dart' as db;
import 'package:villadex/model/address_model.dart';
class Property {
/// Constructors
Property({
required this.name,
required Address address,
required this.owner,
}) : _address = address,
_primaryKey = null,
_dateCreated = DateTime.now();
Property.existing(
{required this.name,
required Address address,
required this.owner,
required int? primaryKey,
required DateTime dateCreated})
: _address = address,
_primaryKey = primaryKey,
_dateCreated = dateCreated;
Property.fromJSON({required Map<String, dynamic> json})
: name = json['name'],
owner = json['owner'],
_address = Address.fromJson(json: json['location']),
_primaryKey = json['property_id'],
_dateCreated = DateTime.fromMillisecondsSinceEpoch(json['dateCreated']);
/// Data
String name;
String? owner;
final Address _address;
/*final List<Event> calendar;
final List<Expenditure> expenditures;
final List<Associate> associates;
final List<Earning> earnings;*/
final int? _primaryKey;
final DateTime _dateCreated;
///Methods
Future<void> insert() async {
String dateCreated = _dateCreated.toIso8601String().trim();
Map<String, dynamic> data = {
// SQFlite sets the primary key
'name': name,
'owner': owner,
'location': address.toJson(),
'dateCreated': dateCreated,
};
await db.DatabaseConnection.database.then((databaseConnection) => {
databaseConnection?.insert('properties', data,
conflictAlgorithm: ConflictAlgorithm.replace)
});
}
static Future<Property?> fetchById(int id) async {
String sql = "SELECT * FROM properties WHERE property_id = $id";
Future<List<Map<String, dynamic>>>? rawData;
await db.DatabaseConnection.database.then(
(databaseConnection) => {rawData = databaseConnection?.rawQuery(sql)});
return rawData?.then((data) {
return Property.fromJSON(json: data[0]);
});
}
/// Getters
Address get address => _address;
}
address_model.dart
import 'package:flutter/material.dart';
import 'package:villadex/model/database.dart' as db;
class Address {
/// Constructors
Address(
{required this.street1,
this.street2 = '',
required this.city,
this.state = '',
this.zip = '',
required this.country})
: _dateCreated = DateTime.now(),
_primaryKey = null,
_propertyId = null,
_associateId = null;
Address.existing({
required this.street1,
this.street2 = '',
required this.city,
this.state = '',
this.zip = '',
required this.country,
required DateTime dateCreated,
required int primaryKey,
int? propertyKey,
int? associateKey,
}) : _dateCreated = dateCreated,
_primaryKey = primaryKey,
_propertyId = propertyKey,
_associateId = associateKey;
Address.fromJson({required Map<String, dynamic> json})
: street1 = json['street1'],
street2 = json['street2'],
city = json['city'],
state = json['state'],
zip = json['zip'],
country = json['country'],
_primaryKey = json['address_id'],
_propertyId = json['property_id'],
_associateId = json['associate_id'],
_dateCreated = DateTime.parse(json['_dateCreated']);
/// Data
final String street1;
final String street2;
final String city;
final String state;
final String zip;
final String country;
final int? _primaryKey;
final int? _propertyId;
final int? _associateId;
final DateTime _dateCreated;
/// Methods
Future<void> insert() async {
Map<String, dynamic> data = {
// SQFlite sets the primaryKey
'property_id': _propertyId,
'associate_id': _associateId,
'dateCreated': _dateCreated.toIso8601String().trim(),
'street1': street1,
'street2': street2,
'city': city,
'zip': zip,
'country': country
};
await db.DatabaseConnection.database.then((databaseConnection) =>
{databaseConnection?.insert('addresses', data)});
}
// Returns an address by ID
static Future<Address?> fetchById(int id) async {
String sql = "SELECT * FROM addresses WHERE address_id = $id";
Future<List<Map<String, dynamic>>>? rawData;
await db.DatabaseConnection.database.then(
(databaseConnection) => {rawData = databaseConnection?.rawQuery(sql)});
return rawData?.then((data) {
return Address.fromJson(json: data[0]);
});
}
Map<String, dynamic> toJson() {
return {
'street1': street1,
'street2': street2,
'city': city,
'state': state,
'zip': zip,
'country': country,
'address_id': _primaryKey,
'property_id': _propertyId,
'associate_id': _associateId,
'dateCreated': _dateCreated
};
}
/// Getters
String get fullAddress =>
street1 +
" " +
street2 +
", " +
city +
" " +
state +
" " +
zip +
", " +
country;
DateTime get dateCreated => _dateCreated;
int get key => _primaryKey ?? 0;
/// Setters
}
database.dart
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:async';
import 'package:villadex/model/property_model.dart';
class DatabaseConnection {
//static final DatabaseConnection instance = DatabaseConnection.init();
//DatabaseConnection._init();
/// Database variable
static Database? _database;
/// Getter for the database
static Future<Database?> get database async {
// If _database is null, set it equal to the return value of _initDB
_database ??= await _initDB('database3');
return _database;
}
/// Initialize database
static Future<Database?> _initDB(String dbname) async {
final dbPath = await getApplicationDocumentsDirectory();
final path = join(dbPath.toString(), dbname);
var dbInstance = await openDatabase(path, version: 1, onCreate: _createDatabase);
return dbInstance;
}
/// Create the database
static Future _createDatabase(Database database, int version) async {
Batch batch = database.batch();
/// CREATE PROPERTIES TABLE
batch.execute('''CREATE TABLE properties(
property_id INTEGER PRIMARY KEY,
dateCreated TEXT NOT NULL,
name TEXT NOT NULL,
location TEXT NOT NULL,
owner TEXT NOT NULL,
calendar TEXT,
expenditures TEXT,
associates TEXT,
earnings TEXT
);''');
/// CREATE EXPENDITURES TABLE
batch.execute('''CREATE TABLE expenditures(
expenditure_id INTEGER PRIMARY KEY,
property_id INTEGER NOT NULL,
dateCreated TEXT NOT NULL,
name TEXT NOT NULL,
amount REAL NOT NULL,
numberUnits INTEGER NOT NULL,
isPaid INTEGER NOT NULL,
description TEXT,
category TEXT,
date TEXT,
associates TEXT,
FOREIGN KEY (property_id)
REFERENCES properties(property_id)
);''');
/// CREATE EARNINGS TABLE
batch.execute(''' CREATE TABLE earnings(
earning_id INTEGER PRIMARY KEY,
property_id INTEGER NOT NULL,
dateCreated TEXT NOT NULL,
name TEXT NOT NULL,
amount REAL NOT NULL,
description TEXT,
category TEXT,
date TEXT,
associates TEXT,
FOREIGN KEY (property_id)
REFERENCES properties(property_id)
);''');
/// CREATE CATEGORIES TABLE
batch.execute(''' CREATE TABLE categories(
category_id INTEGER NOT NULL,
dateCreated TEXT NOT NULL,
name TEXT NOT NULL
);''');
/// CREATE ASSOCIATES TABLE
batch.execute(''' CREATE TABLE associates(
associate_id INTEGER PRIMARY KEY,
property_id INTEGER NOT NULL,
dateCreated TEXT NOT NULL,
name TEXT NOT NULL,
contact TEXT,
role TEXT,
payments TEXT,
FOREIGN KEY (property_id)
REFERENCES properties (property_id)
);''');
/// CREATE CONTACTS TABLE
batch.execute(''' CREATE TABLE contact (
associate_id INTEGER NOT NULL,
phoneNumber TEXT,
email TEXT,
FOREIGN KEY (associate_id)
REFERENCES associates (associate_id)
);''');
/// CREATE ADDRESSES TABLE
batch.execute(''' CREATE TABLE addresses (
address_id INTEGER PRIMARY KEY,
property_id INTEGER,
associate_id INTEGER,
dateCreated TEXT NOT NULL,
street1 TEXT NOT NULL,
street2 TEXT,
city TEXT NOT NULL,
zip TEXT,
state TEXT,
country TEXT,
FOREIGN KEY (property_id)
REFERENCES properties (property_id),
FOREIGN KEY (associate_id)
REFERENCES associates (associate_id)
);''');
/// CREATE EVENT TABLE
batch.execute(''' CREATE TABLE event (
event_id INTEGER PRIMARY KEY,
property_id INTEGER NOT NULL,
dateCreated TEXT NOT NULL,
name TEXT NOT NULL,
description TEXT,
address TEXT,
associates TEXT,
expenditures TEXT,
earnings TEXT,
FOREIGN KEY (property_id)
REFERENCES properties (property_id)
);''');
batch.commit();
}
Future close() async {
_database?.close;
}
}
Thank you for any help!
I figured it out. The address object within my property object did not turn its DateTime object into a string during the address.toJson() method, which is why it was giving me that error.
I am wondering if it is possible to configure epplus in such a way that when the excel file is opened the table data can be clicked on and a graph will be displayed based on the row of the table clicked. (I realize this is super easy to do in excel I would just rather have everything taken care of before it gets to certain people)
Currently I just have one data table and a graph for each row but it would be better if there was just one graph that changed based on what row is clicked in excel. I also tried a pivot table but that doesn't help me with the dynamic chart.
For anyone trying to figure this out as well. I ended up using a data validation drop down list and making a dynamic table row (outside the base table) that the dynamic chart is based on. The dynamic table row changes based on the value of the data validation dropdown list (you kinda need a feel for excel to be able to do this which I didn't have):
class Program
{
static void Main(string[] args)
{
// Creating an instance
// of ExcelPackage
ExcelPackage excel = new ExcelPackage();
// name of the sheet
var workSheet = excel.Workbook.Worksheets.Add("testSheet");
//init table
var randTable = new DataTable();
randTable.TableName = "randTable";
//init columns
var countColumn = new DataColumn()
{
DataType = typeof(int),
ColumnName = "Count",
ReadOnly = true,
Unique = true
};
var randomColumn0 = new DataColumn()
{
DataType = typeof(int),
ColumnName = "Random-0",
ReadOnly = true,
Unique = false
};
var randomColumn1 = new DataColumn()
{
DataType = typeof(int),
ColumnName = "Random-1",
ReadOnly = true,
Unique = false
};
//add columns to table
randTable.Columns.AddRange(new DataColumn[] { countColumn, randomColumn0, randomColumn1 });
//init data validation
ExcelRange dropdownRange = workSheet.Cells[12, 1, 12, 3];
var dropdownValidation = workSheet.DataValidations.AddListValidation(dropdownRange.Address);
workSheet.Names.Add("count", dropdownRange);
//style data validation
dropdownRange.Merge = true;
workSheet.Cells[dropdownRange.Address].Style.Fill.PatternType = ExcelFillStyle.Solid;
workSheet.Cells[dropdownRange.Address].Style.Fill.BackgroundColor.SetColor(Color.Yellow);
workSheet.Cells[dropdownRange.Address].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
var rand = new Random();
for (var i = 0; i < 10; i++)
{
//add table first column values to validation list
dropdownValidation.Formula.Values.Add(i.ToString());
var row = randTable.NewRow();
row[countColumn] = i;
row[randomColumn0] = rand.Next(0, 100);
row[randomColumn1] = rand.Next(0, 100);
randTable.Rows.Add(row);
}
//make the tableIndexer cell. This cell will be used to get the
//table indices for the selected table row cells
ExcelRange randTableIndexer = workSheet.Cells[12, 4, 12, 4];
randTableIndexer.Formula = "MATCH(INDEX(count,1,1), randTable[Count], 0)";
workSheet.Cells[randTableIndexer.Address].Style.Fill.PatternType = ExcelFillStyle.Solid;
workSheet.Cells[randTableIndexer.Address].Style.Fill.BackgroundColor.SetColor(Color.LightGreen);
workSheet.Cells[randTableIndexer.Address].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
workSheet.Names.Add("tableIndex", randTableIndexer);
//make the cells based off the table at row(randTableIndexer.value)
ExcelRange graphCells = workSheet.Cells[13, 1, 13, 3];
graphCells.CreateArrayFormula("INDEX(randTable[], tableIndex, 0)"); //need [] on table names in epplus formulas
workSheet.Cells[graphCells.Address].Style.Fill.PatternType = ExcelFillStyle.Solid;
workSheet.Cells[graphCells.Address].Style.Fill.BackgroundColor.SetColor(Color.LightBlue);
workSheet.Cells[graphCells.Address].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
graphCells.Calculate();
//add table to workSheet
workSheet.Cells[1, 1].LoadFromDataTable(randTable, true, OfficeOpenXml.Table.TableStyles.Medium15);
workSheet.Cells.AutoFitColumns();
//add dynamic chart
var chart = workSheet.Drawings.AddChart("rands", eChartType.Pie) as ExcelPieChart;
chart.Title.Text = "rands";
chart.Series.Add(graphCells.Address, ExcelRange.GetAddress(1, 1, 3, 1));
chart.Legend.Position = eLegendPosition.Bottom;
chart.SetSize(500, 400);
chart.SetPosition(60, 500);
WriteToFile(excel);
}
public static void WriteToFile(ExcelPackage package)
{
// file name with .xlsx extension
string p_strPath = "C:\\your\\file\\path";
if (File.Exists(p_strPath))
File.Delete(p_strPath);
// Create excel file on physical disk
FileStream objFileStrm = File.Create(p_strPath);
objFileStrm.Close();
// Write content to excel file
File.WriteAllBytes(p_strPath, package.GetAsByteArray());
}
}
I want to call an method with invoke. My object input is a string that is address of a file in my computer and type of output is IDispatch. How I should define Disparams as an input of invoke. My code is :
::CLSIDFromProgID(OLESTR("SGNSAutomation.SGNSApplication"), &clsid);
IID iid;
HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL,
IID_IDispatch, (LPVOID*)&pWMPDispatch);
IDispatch * pdisp = (IDispatch *)NULL;
DISPID dispid;
DISPPARAMS params= {NULL,NULL,0,0};
OLECHAR * Name = OLESTR("importCase");
//my problem is here
params.rgvarg[1].pdispVal
params.rgvarg[0].bstrVal="E:\\new library\\university\\final project
documentation\\GPNS project\\net1.gpns";
params.rgvarg[1].scode = DISP_E_PARAMNOTFOUND;
params.cArgs = 2;
params.cNamedArgs = 0;
//
pWMPDispatch->GetIDsOfNames(IID_NULL,
&Name,1,LOCALE_SYSTEM_DEFAULT,&dispid);
HRESULT hresult =pWMPDispatch->Invoke(dispid, IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶ms, NULL, NULL,
NULL);
please help me to define disparams correctly.
i have an enum declared as
enum class AccessLevel : int
{
ReadOnly = 0,
Excluded = 1,
ReadWrite = 2,
};
and an Array declared as
static array<String^>^ _accessMap = gcnew array<String^> { "R", "X", "W" };
I want to do something like this:
AccessLevel^ access = access::ReadOnly;
String^ foo = _accessMap[access];
public enum struct AccessLevel
{
ReadOnly = 0,
Excluded = 1,
ReadWrite = 2,
};
AccessLevel access = access::ReadOnly;
you might need to cast to an int
String^ foo = _accessMap[(int)access];