I have an xlsx excel table and I need to convert it into a List<Object> and take just the following columns: D, F, H, J, L. I'm trying everything but nothing works.
I'm using the following plugin to do it:
file_picker
excel
Does anyone know how can I convert it?
Table
Here is my example code:
import 'package:adminpanelweb/models/import_users.dart';
import 'package:excel/excel.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
Future importUsers(BuildContext context, String palaceId) async {
FilePickerResult? pickedFile = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['xlsx'],
allowMultiple: false,
);
if (pickedFile != null) {
var bytes = pickedFile.files.single.bytes;
var excel = Excel.decodeBytes(bytes!);
List<ImportUsers> users = [];
List<String> stringList = [];
for (var table in excel.tables.keys) {
for (var rows in excel.tables[table]!.rows) {
// print(
// '${rows.toString().isNotEmpty ? rows.map((e) => e?.value).toList() : ''}',
// );
stringList.add(
'${rows.toString().isNotEmpty ? rows.map((e) => e?.value).toList() : ''}');
}
}
final regExp = RegExp(r'(?:\[)?(\[[^\]]*?\](?:,?))(?:\])?');
final input = stringList.toString();
final result = regExp
.allMatches(input)
.map((m) => m.group(1))
.map((String? item) => item?.replaceAll(RegExp(r'[\[\]]'), ''))
.map((m) => [m])
.toList();
for (var items in result) {
users = items.map((e) {
return {
"field1": e?[0],
"WEB": e?[1],
"R": e?[2],
"Denominazione": e?[3],
"Data Uscita": e?[4],
"Codice Fiscale": e?[5],
"Partita IVA": e?[6],
"Username": e?[7],
"field9": e?[8],
"Password": e?[9],
"Profilo": e?[10],
"Email": e?[11],
};
}).toList() as List<ImportUsers>;
print(items);
}
// print('sadasdasdasdsad ${users.length}');
}
}
After some hours I solved as it:
Future importUsers(BuildContext context, String palaceId) async {
FilePickerResult? pickedFile = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['xlsx'],
allowMultiple: false,
);
if (pickedFile != null) {
List<User> xlsxToList = [];
var bytes = pickedFile.files.single.bytes;
var excel = Excel.decodeBytes(bytes!);
for (var table in excel.tables.keys) {
for (var row in excel.tables[table]!.rows) {
xlsxToList.add(
User(
userEmail: row[11]?.value.toString(),
userUsername: row[7]?.value.toString(),
userName: row[3]?.value.toString(),
userCf: row[5]?.value.toString(),
userPassword: row[9]?.value.toString(),
),
);
}
}
xlsxToList.removeAt(0);
print('__________ ${userToJson(xlsxToList)}');
}
}
Related
I'm trying to make a comparison function. If the value that I search is not exist, the new value will be save to the database. But all I get is 0 new data found. So the system decides to not save the data. Is my searching wrong?
This is my code:
var count = 0;
for (var t = 1; t < 151; t++) {
var searching = JobsSchema.find({ jobName: name[t], company: company[t] })
if (searching == null) {
count = count + 1;
var newJobs = new JobsSchema({
"jobName": name[t],
"country": country[t],
"company": company[t],
"jobType": type[t],
"salary": salary[t],
"skills": skills[t],
"jobDesc": desc[t],
"jobReq": req[t],
"jobResponsibility": resp[t],
"industry": industry[t],
})
newJobs.save(function (err, result) {
if (err) {
console.log(err);
}
})
}
}
console.log(count + " new data found.");
You should await your find function.
Also, change it to findOne to return a single instance of the JobsSchema and await the save call as well.
Finally you will need to wrap the code into an async function:
const saveData = async () => {
var count = 0;
for (var t = 1; t < 151; t++) {
var searching = await JobsSchema.findOne({
jobName: name[t],
company: company[t],
});
if (!searching) {
count = count + 1;
var newJobs = new JobsSchema({
jobName: name[t],
country: country[t],
company: company[t],
jobType: type[t],
salary: salary[t],
skills: skills[t],
jobDesc: desc[t],
jobReq: req[t],
jobResponsibility: resp[t],
industry: industry[t],
});
await newJobs.save();
}
}
console.log(count + ' new data found.');
};
saveData();
I am making a Type racing minigame with my discord bot, the code works... but I want to change the messages it sends to embeds, im new to Commando and it wont let me use the discord.js functions im used to using
I need to change all the bots responses to embeds, and make it so when it sends a new embed it just edits the old one so it isnt spamming messages. Here is my code:
const Commando = require('discord.js-commando')
const { words } = require('../../util/fast-type-words')
const example = {
channelId: {
message: 'message object',
stage: 'string',
counter: 'number',
currentWord: 'string',
remainingWords: ['words here'],
points: {
userId: 'points',
},
},
}
const games = {}
const stages = {
STARTING: (counter) => {
return `A new "fast type" game is starting in ${counter}s!`
},
IN_GAME: (word) => {
let spacedWord = ''
for (const character of [...word]) {
spacedWord += character
spacedWord += ' '
}
return `The new word is **${spacedWord}**!`
},
ENDING: (points) => {
const sorted = Object.keys(points).sort((a, b) => {
return points[b] - points[a]
})
let results = ''
for (const key of sorted) {
const amount = points[key]
results += `<#${key}> had ${amount} point${amount === 1 ? '' : 's'}\n`
}
return `The game is now over Here's how everyone did:\n\n${results}------------------`
},
}
const selectWord = (game) => {
game.currentWord =
game.remainingWords[Math.floor(Math.random() * game.remainingWords.length)]
const index = game.remainingWords.indexOf(game.currentWord)
game.remainingWords.splice(index, 1)
}
const gameLoop = () => {
for (const key in games) {
const game = games[key]
const { message, stage } = game
if (stage === 'STARTING') {
let string = stages[stage](game.counter)
message.edit(string)
if (game.counter <= 0) {
game.stage = 'IN_GAME'
game.counter = 15
selectWord(game)
string = stages[game.stage](game.currentWord)
message.edit(string)
}
} else if (stage === 'IN_GAME') {
if (game.counter <= 0) {
game.stage = 'ENDING'
const string = stages[game.stage](game.points)
message.edit(string)
// Delete the game
delete games[key]
continue
}
}
--game.counter
}
setTimeout(gameLoop, 1000)
}
module.exports = class FastTypeGame extends Commando.Command {
constructor(client) {
super(client, {
name: 'fasttype',
group: 'games',
memberName: 'fasttype',
description: 'Starts a fast type game',
userPermissions: ['ADMINISTRATOR'],
})
client.on('message', (message) => {
const { channel, content, member } = message
const { id } = channel
const game = games[id]
if (game && game.currentWord && !member.user.bot) {
message.delete()
if (
game.stage === 'IN_GAME' &&
content.toLowerCase() === game.currentWord.toLowerCase()
) {
game.currentWord = null
const seconds = 2
const { points } = game
points[member.id] = points[member.id] || 0
message
.reply(`You won! +1 point (${++points[member.id]} total)`)
.then((newMessage) => {
newMessage.delete({
timeout: 1000 * seconds,
})
})
setTimeout(() => {
if (game.stage === 'IN_GAME') {
selectWord(game)
const string = stages[game.stage](game.currentWord)
game.message.edit(string)
}
}, 1000 * seconds)
}
}
})
gameLoop()
}
async run(message) {
const { channel } = message
message.delete()
channel.send('Preparing game...').then((message) => {
games[channel.id] = {
message,
stage: 'STARTING',
counter: 5,
remainingWords: [...words],
points: {
'719805930547445772': 4,
'723819104045105172': 1,
},
}
})
}
}
First change embeded content is not related to discord.js-commando to change the content of sended embeded message you need to get Message Object then using edit() method to pass the new embed content to it:
-Bonus: You can also edit text message into embed message.
Docs for edit method: https://discord.js.org/#/docs/main/stable/class/Message?scrollTo=edit
Example code:
let youCurrentMessage = await channel.send(embedContent);
yourCurrentMessage.edit(newEmbedContent);
yourCurrentMessage.edit(newEmbedContent2);
// If you edit message in other command , session.You need message id
let yourCurrentMessage = await msg.channel.messages.fetch(editMessageId);
yourCurrentMessage.edit(newEmbedContent);
Here is the RESTful API response json:
{
"success": true,
"data": {
"loginname": "mrdulin",
"avatar_url": "https://avatars1.githubusercontent.com/u/1147375?v=4&s=120",
"githubUsername": "mrdulin",
"create_at": "2012-09-09T05:26:58.319Z",
"score": 15835,
"recent_topics": [
{
"id": "5c6d11d033b0b629ac8434ef",
"author": {
"loginname": "mrdulin",
"avatar_url": "https://avatars1.githubusercontent.com/u/1147375?v=4&s=120"
},
"title": "grpc and Node.js",
"last_reply_at": "2019-05-11T04:22:18.616Z"
}
],
"recent_replies": []
}
}
UserServiceImpl.ts:
export class UserServiceImpl implements IUserServiceServer {
public async getUserByLoginname(call: ServerUnaryCall<GetUserByLoginnameRequest>, callback: sendUnaryData<GetUserByLoginnameResponse>) {
const loginname = call.request.getLoginname();
const url = `${config.CNODE_API_URL}/user/${loginname}`;
try {
const res = await axios.get(url);
const data = res.data.data;
// map API response js plain object to GetUserByLoginnameResponse
const grcpResponse = new GetUserByLoginnameResponse();
grcpResponse.setSuccess(res.data.success);
const user = new UserDetail();
user.setAvatarUrl(data.avatar_url);
user.setLoginname(data.loginname);
user.setGithubusername(data.githubUsername);
user.setCreateAt(data.create_at);
user.setScore(data.score);
const recentReplies = data.recent_replies.map((po) => {
const reply = new RecentReply();
reply.setId(po.id);
reply.setTitle(po.title);
const lastReplyAt = new google_protobuf_timestamp_pb.Timestamp();
lastReplyAt.fromDate(new Date(po.last_reply_at));
reply.setLastReplyAt(lastReplyAt);
const author = new UserBase();
author.setLoginname(po.author.loginname);
author.setAvatarUrl(po.author.avatar_url);
reply.setAuthor(author);
return reply;
});
const recentTopics = data.recent_topics.map((po) => {
const topic = new TopicBase();
topic.setId(po.id);
topic.setTitle(po.title);
topic.setLastReplyAt(po.last_reply_at);
const author = new UserBase();
author.setLoginname(po.author.loginname);
author.setAvatarUrl(po.author.avatar_url);
topic.setAuthor(author);
return topic;
});
user.setRecentRepliesList(recentReplies);
user.setRecentTopicsList(recentTopics);
grcpResponse.setData(user);
callback(null, grcpResponse);
} catch (error) {
console.error(error);
const metadata = new Metadata();
metadata.set('url', url);
const ErrGetUserByLoginname: ServiceError = {
code: status.INTERNAL,
name: 'getUserByLoginnameError',
message: 'call CNode API failed',
metadata,
};
callback(ErrGetUserByLoginname, null);
}
}
}
As you can see, I have to map the plain javascript object(the API response) to GetUserByLoginnameResponse class manually. This is cumbersome and inefficient.
I am using static codegen, so the GetUserByLoginnameResponse class is generated based on IDL defined in the .proto files.
user.service.proto:
service UserService {
rpc GetUserByLoginname(GetUserByLoginnameRequest)
returns (GetUserByLoginnameResponse);
}
message GetUserByLoginnameRequest { string loginname = 1; }
message GetUserByLoginnameResponse {
UserDetail data = 1;
bool success = 2;
}
message UserDetail {
string loginname = 1;
string avatar_url = 2;
string githubUsername = 3;
string create_at = 4;
int32 score = 5;
repeated share.TopicBase recent_topics = 6;
repeated reply.RecentReply recent_replies = 7;
}
I am trying to implement a simple extraction function that connects to the Poloniex.returnTicker endpoint and, extract the 'last' key for any currency pairs starting with 'BTC'. There are a number of keys starting with 'BTC' but, my extraction function is stopping after returning exactly one key. I am mapping the extracted data in an object in the following manner:
extracted = {
BTC: {
STR: {
lastPrice: price
},
ETH: {
lastPrice: price
}, //...
}, //...
}
I wrote the following function for extraction:
module.exports = {
extractData: (tickerdata, marker) => {
if(!!!marker){
marker = 'BTC';
}
return new Promise((res, rej) => {
let currentBuffer = {};
Object.keys(tickerdata)
.filter((key) => {
return key.startsWith(marker);
})
.forEach((filtKey) => {
let c = filtKey.split('_'),
src = c[0],
dst = c[1];
currentBuffer[src] = {};
Object.keys(tickerdata[filtKey])
.forEach((entry) => {
if(!!!(dst in currentBuffer[src])){
currentBuffer[src][dst] = {};
}
if(entry == 'last'){
currentBuffer[src][dst]['lastPrice'] = tickerdata[filtKey][entry];
}
});
});
res(currentBuffer);
});
},//... rest of the module exports
For reference, each call to return ticker endpoint returns data in the following format: Poloniex API. Look at returnTicker endpoint for example.
I am guessing that there is a logical error in the extraction function but, I am not sure where.
UPDATE
What about this code?
module.exports = {
extractData: (tickerdata, marker) =>
Object.keys(tickerdata)
.map(x => x.split('_'))
.filter(x => x && x[0] == (marker || 'BTC') && x[1])
.map(x => x[0] + '_' + x[1])
.map(x => [x, Object.keys(tickerdata[x])
.map(y => [y, tickerdata[x][y].lastPrice])]);
and usage:
const extracted = {
ETH_STR: {
BTC: {
lastPrice: 1
}
},
BTC_ETH: {
STR: {
lastPrice: 1
}
},
BTC_STR: {
STR: {
lastPrice: 1
},
ETH: {
lastPrice: 2
}, //...
}, //...
};
const result = extractData(extracted, 'BTC');
console.log(JSON.stringify(result));
with result
[["BTC_ETH",[["STR",1]]],["BTC_STR",[["STR",1],["ETH",2]]]]
I have tinkered around with my code and, finally was able to make it work. Besides adding more code for extracting data from the API response object, tickerdata, I have changed the promise to return instead of resolve. This ensured that the flow remains in proper sequence. I used a then clause on the promise to retrieve the extracted values (named buff). Here is the full working code:
`module.exports = {
extractData: (markers) => {
// extracts the data for all markers which, are a comma separated string of base currencies
return new Promise((res, rej) => {
markers = (!!!(markers) ? 'USDT,BTC' : markers)
polinst.returnTicker()
.then((tickerdata) => {
let buff = {};
markers.split(',').forEach((marker) => {
Object.keys(tickerdata)
.filter((key) => {
return key.startsWith(marker);
})
.forEach((fkey) => {
let c = fkey.split('_'),
src = c[0],
dst = c[1];
buff[src] = (!!!(buff[src]) ? {} : buff[src]);
buff[src][dst] = (!!!(buff[src][dst]) ? {} : buff[src][dst]);
Object.keys(tickerdata[fkey])
.forEach((k) => {
if(k == 'last'){
buff[src][dst]['lastPrice'] = tickerdata[fkey][k];
}
else if(k == 'quoteVolume'){
buff[src][dst]['volume'] = tickerdata[fkey][k];
}
else if(k == 'lowestAsk'){
buff[src][dst]['ask'] = tickerdata[fkey][k];
}
else if(k == 'highestBid'){
buff[src][dst]['highestBid'] = tickerdata[fkey][k];
}
});
});
});
return buff;
}).then((d)=>{
res(d);
}).catch((err)=>{
console.log(err);
});
});
},
};`
I have this error:
TypeError: $(element).slider is not a function
with the following script:
Rickshaw.namespace('Rickshaw.Graph.RangeSlider');
Rickshaw.Graph.RangeSlider = function(args) {
var element = this.element = args.element;
var graph = this.graph = args.graph;
$( function() {
$(element).slider( {
range: true,
min: graph.dataDomain()[0],
max: graph.dataDomain()[1],
values: [
graph.dataDomain()[0],
graph.dataDomain()[1]
],
slide: function( event, ui ) {
graph.window.xMin = ui.values[0];
graph.window.xMax = ui.values[1];
graph.update();
// if we're at an extreme, stick there
if (graph.dataDomain()[0] == ui.values[0]) {
graph.window.xMin = undefined;
}
if (graph.dataDomain()[1] == ui.values[1]) {
graph.window.xMax = undefined;
}
}
} );
} );
$(element)[0].style.width = graph.width + 'px';
graph.onUpdate( function() {
var values = $(element).slider('option', 'values');
$(element).slider('option', 'min', graph.dataDomain()[0]);
$(element).slider('option', 'max', graph.dataDomain()[1]);
if (graph.window.xMin == undefined) {
values[0] = graph.dataDomain()[0];
}
if (graph.window.xMax == undefined) {
values[1] = graph.dataDomain()[1];
}
$(element).slider('option', 'values', values);
} );
};
From the following page:
https://github.com/shutterstock/rickshaw/blob/master/src/js/Rickshaw.Graph.RangeSlider.js
The javascript debugger show me this line: slide: function( event, ui ) {
Can you show me a way to resolve my problem. Thanks you!
You should import jqueryui before using the slider.
http://jqueryui.com/slider/