DataTable into excel via OpenXML - excel

I have a DataTable like this
Col1 Col2 Col3 col4
GRPs 2009 69952.4 a
GRPs 2010 58949.8 a
GRPs 2009 37251.2 b
GRPs 2010 35433.9 b
GRPs 2009 28039.2 c
GRPs 2010 35079.4 c
SOC 2009 69952.4 a
SOC 2010 58949.8 a
SOC 2009 37251.2 b
SOC 2010 35433.9 b
SOC 2009 28039.2 c
SOC 2010 35079.4 c
And I need a to "transform" it to a excel file using OpenXML with this format
A B C D E F G H I
1 2009 2010 2009 2010 2009 2010
2 GRPs 69952.4 58949.8 37251.2 35433.9 28039.2 35079.4
3 SOC 69952.4 58949.8 37251.2 35433.9 28039.2 35079.4
Thanks in advance

It goes a little like this (sorry this isn't the complete code but it should help):
//Column headers
static string[] headerColumns = new string[] { "A", "B", "C" };
//Used for header column counting
static string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
foreach (char c in alphabet.Split(alphabet[dt.Columns.Count])[0])
headerColumns[alphabet.IndexOf(c)] = c.ToString();
//Loops through the data table and appends the data rows onto sheet data
for (int r = 0; r < dt.Rows.Count; r++)
{
//Builds a list of values from the data row
List<string> values = new List<string>();
for (int i = 0; i < dt.Columns.Count; i++)
values.Add(dt.Rows[r][i].ToString());
//Creates a spreadsheet row from the list of values
Spreadsheet.Row contentRow = CreateContentRow(values, r + 2);
//Appends the row to the sheetData
sheetData.AppendChild(contentRow);
}
private static Spreadsheet.Row CreateContentRow(List<string> values, int index)
{
//Create the new row.
Spreadsheet.Row r = new Spreadsheet.Row();
r.RowIndex = (UInt32)index;
//Create the cells that contain the data.
for (int i = 0; i < headerColumns.Length; i++)
{
Spreadsheet.Cell c = new Spreadsheet.Cell();
c.CellReference = headerColumns[i] + index;
Spreadsheet.CellValue v = new Spreadsheet.CellValue();
v.Text = values[i];
c.AppendChild(v);
r.AppendChild(c);
}
return r;
}

Related

JavaFX adding ObservableList<String> to single column TableView

I want to add the data from ObservableList batchNumber to a tableview which only contains one column yet im stucked because all the tutorials i found is about adding object type, not string type.
This is a function i used to generate a random batch number of format AAA0000
public String generateBatch(){
Random rand = new Random();
String[] alphabet = "Q W E R T Y U I O P A S D F G H J K L Z X C V B N M".split(" ");
String batch = new String();
batch = alphabet[rand.nextInt(0, 26)] + alphabet[rand.nextInt(0, 26)] + alphabet[rand.nextInt(0, 26)] + rand.nextInt(1000, 9999);
return batch;
}
and then i add bunch of batch number into a ObservableList
ObservableList<String> batchNumber = FXCollections.observableArrayList();
for(int i = 0; i < 10; i++){
batchNumber.add(generateBatch());
}
so now batchNumber is loaded with bunch of Strings and then i tried to assign them to a tableView
TableView<String> batchNumberTableView = new TableView<>();
TableColumn<String, ?> batchColumn = new TableColumn<>("Vaccine Batch Number");
batchNumberTableView.getColumns().add(batchColumn);
and here is where im stucked, i've had successfully added a column into the tableview but i have no idea how to assign the datas from batchNumber into the tableview.
You need
TableColumn<String, String> batchColumn = new TableColumn<>("Vaccine Batch Number");
batchColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue()));

Excel table to DataTable (VSTO)

I have an Excel VSTO Add-in, and I have to get excel table data into a DataTable class, I've already implemented it by looping through the cells but its a bit slow:
DataTable dataTable = new DataTable(table.Name);
foreach (Excel.ListColumn column in table.ListColumns)
dataTable.Columns.Add(column.Name);
for (int r = 2; r < table.ListRows.Count + 2; r++)
{
DataRow row = dataTable.NewRow();
for (int c = 1; c < table.ListColumns.Count + 1; c++)
row[c - 1] = ((Excel.Range)table.Range[r, c]).Value;
dataTable.Rows.Add(row);
}
So my question is, is there any Method (or fast way) in Excel interop to export table data to a DataTable class?
Thanks
You can read all values in the DataBodyRange of your table (a ListObject I deduce) at once, into a 1-based 2D object array, like so:
var theValues = table.DataBodyRange.Value;
It's then just a matter of scanning this array.

Developing Visual Studio Universal Project - How to extract text from sequential named TextBoxes in for loop

I have a problem with the following code which I thought would extract user input from sequential TextBoxes on a form:
#include "pch.h"
#include "MainPage.xaml.h"
#include <iostream> // for std::cout and std::cin
#include <sstream>
#include <string>
{
int grid[9][9] = { 0 }; // virtual array filled with zeros
//put numbers in array
for (int row = 0; row < 9; ++row)//step through all rows
for (int col = 0; col < 9; ++col) //step through all columns
{
row = row + 1; // text box names suffixes are 11 to 19
col - col + 1;
std::string r_str = std::to_string(row);// turn row number into text
std::string c_str = std::to_string(col);//turn column nuber into text
std::string texnum = "Tex" + r_str + c_str;// eg "Tex11" //compile textbox name
String^ str_input = texnum->Text; //get Platform::String from textBox
std::wstring wsstr(str_input->Data());//Convert Platform::String to String
int n = std::stoi(wsstr);//Convert String to Integer
grid[row][col] = n; //put text from texbox in array as a number
}
}
On the line
String^ str_input = texnum->Text;
At the TexBox Identifier of texnum it gives an error of Expression must have a pointer or handle type. If I replace it with an actual Textbox name Tex11 there is no Error but then it only extract text from one box.
I need a way to get text from a TextBox using a string variable instead of the actual string.
Any help would be appreciated.
You can't directly use the string to try to get the Text property, in that case, it is only a string instead of TextBox object. So you need to first get the TextBox control by the name string you get and then get the Text property by the TextBox.
You can try the following code to use the FindName method to get the TextBox object, the "MyPage" is the parent view of TextBox(e.g. StackPanel). In addition, the FindName method needs to be passed the PlatForm::String^ type, it's easy to convert std::wstring to PlatForm::String^, so it's better to only use std::wstring type instead of std::string.
int grid[9][9] = { 0 }; // virtual array filled with zeros
//put numbers in array
for (int row = 0; row < 9; ++row)//step through all rows
for (int col = 0; col < 9; ++col) //step through all columns
{
row = row + 1; // text box names suffixes are 11 to 19
col - col + 1;
std::wstring r_str = std::to_wstring(row);// turn row number into text
std::wstring c_str = std::to_wstring(col);//turn column nuber into text
std::wstring texnum = L"texnum" + r_str + c_str;
Platform::String^ aa = ref new Platform::String(texnum.c_str());
TextBox^ elment = (TextBox ^)MyPage->FindName(ref new Platform::String(texnum.c_str()));
String^ str_input = elment->Text;
std::wstring wsstr(str_input->Data());
int n = std::stoi(wsstr);
}
Here is my final code (The StackPanel is named FirstLine)
void universal::MainPage::Solve_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
int grid[9][9] = { 0 }; // virtual array filled with zeros
//put numbers in array
for (int row = 0; row < 9; ++row)//step through all rows
for (int col = 0; col < 9; ++col) //step through all columns
{
row = row + 1; // text box names suffixes are 11 to 19
col = col + 1;
std::wstring r_str = std::to_wstring(row);// turn row number into text
std::wstring c_str = std::to_wstring(col);//turn column nuber into text
std::wstring texnum = L"texnum" + r_str + c_str;
Platform::String^ aa = ref new Platform::String(texnum.c_str());
TextBox^ elment = (TextBox^)FirstLine->FindName(aa);
String^ str_input = elment->Text;
std::wstring wsstr(str_input->Data());
int n = std::stoi(wsstr);
}

Sort elements of a NumericMatrix by dim names

I have a NumericMatrix m. Say m is (the elements in the square brackets are the dim names)
7 9 8
4 6 5
1 3 2
with column names = {"x", "z", "y"}, row names = {"z", "y", "x"}
I want the following output
1 2 3
4 5 6
7 8 9
with column names = {"x", "y", "z"}, row names = {"x", "y", "z"}
So what I want to do is the following -
Sort elements of each row according to the column names
Permute the rows such that their corresponding row names are sorted
Is there an easy way to do this in Rcpp for a general NumericMatrix?
This isn't necessarily the simplest approach, but it appears to work:
#include <Rcpp.h>
#include <map>
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::export]]
Rcpp::NumericMatrix dim_sort(const Rcpp::NumericMatrix& m) {
Rcpp::Function rownames("rownames");
Rcpp::Function colnames("colnames");
Rcpp::CharacterVector rn = rownames(m);
Rcpp::CharacterVector cn = colnames(m);
Rcpp::NumericMatrix result(Rcpp::clone(m));
Rcpp::CharacterVector srn(Rcpp::clone(rn));
Rcpp::CharacterVector scn(Rcpp::clone(cn));
std::map<std::string, int> row_map;
std::map<std::string, int> col_map;
for (int i = 0; i < rn.size(); i++) {
row_map.insert(std::pair<std::string, int>(Rcpp::as<std::string>(rn[i]), i));
col_map.insert(std::pair<std::string, int>(Rcpp::as<std::string>(cn[i]), i));
}
typedef std::map<std::string, int>::const_iterator cit;
cit cm_it = col_map.begin();
int J = 0;
for (; cm_it != col_map.end(); ++cm_it) {
int I = 0;
int j = cm_it->second;
scn[J] = cm_it->first;
cit rm_it = row_map.begin();
for (; rm_it != row_map.end(); ++rm_it) {
int i = rm_it->second;
result(J, I) = m(j, i);
srn[I] = rm_it->first;
I++;
}
J++;
}
result.attr("dimnames") = Rcpp::List::create(srn, scn);
return result;
}
/*** R
x <- matrix(
c(7,9,8,4,6,5,1,3,2),
nrow = 3,
dimnames = list(
c("x", "z", "y"),
c("z", "y", "x")
),
byrow = TRUE
)
R> x
z y x
x 7 9 8
z 4 6 5
y 1 3 2
R> dim_sort(x)
x y z
x 1 2 3
y 4 5 6
z 7 8 9
*/
I used a std::map<std::string, int> for two reasons:
maps automatically maintain a sorted order based on their keys, so by using the dim names as keys, the container does the sorting for us.
Letting a key's corresponding value be an integer representing the order in which it was added, we have an index for retrieving the appropriate value along a given dimension.

Duplicate row check in a datatable using C#

I have data table like below. Here row 2,3,4,5 are not allowed. how do i validate this scenario using C#. Please help. Here the number of columns is not fixed.
A B C
A B C
A B
A C
B C
A B B
B B C
A C B
C# with LinQ
This function eliminates duplicates and null values from columns. If is not null what you are looking for, then you just need to change "DBNull" for what you want.
public static DataTable FilterDataTable(DataTable table)
{
// Erase duplicates
DataView dv = new DataView(table);
table = dv.ToTable(true, table.Columns.Cast<DataColumn>().Select(x => x.ColumnName).ToArray());
// Get Null values
List<DataRow> toErase = new List<DataRow>();
foreach (DataRow item in table.Rows)
for (int i = 0; i < item.ItemArray.Length; i++)
{
if (item.ItemArray[i].GetType().Name == "DBNull")
{ toErase.Add(item); break; }
}
//Erase Null Values
foreach (DataRow item in toErase)
table.Rows.Remove(item);
return table;
}

Resources