I'm trying to automate testing of excel add-in that allows you to create some analysis entities based on pivot table definition.
I'm able to create random pivot table using cubefield objects(I'm adding random fields to rows,columns, and measures) but I need also to add some filtering and here I'm stuck.
Is there any way to get cubefield item list ? For example when I have date field in filter
list of all days and then I want to select some random days for filtering.
This is my code maybe it's not elegant but it works for my purpose.
I'm basically grabbing cubefields check if it's measure or dimension and then I'm setting
it's orientation.
public void PivotTableFieldList()
{
_currentPivotTable = (Excel.PivotTable) _worksheet.PivotTables("PivotTable1");
_currentPivotTable.ManualUpdate = true;
List<Excel.CubeField> measureList = new List<Excel.CubeField>();
List<Excel.CubeField> dimensionList = new List<Excel.CubeField>();
foreach (Excel.CubeField field in _currentPivotTable.CubeFields)
{
if (field.CubeFieldType == Excel.XlCubeFieldType.xlMeasure && field.ShowInFieldList)
{
measureList.Add(field);
}
}
foreach (Excel.CubeField field in _currentPivotTable.CubeFields)
{
if (field.CubeFieldType != Excel.XlCubeFieldType.xlMeasure && field.ShowInFieldList)
{
dimensionList.Add(field);
}
}
Random dimRan=new Random();
dimRan.Next(0, dimensionList.Count);
Random mesRan = new Random();
mesRan.Next(0, measureList.Count);
dimensionList.ToArray();
measureList.ToArray();
Excel.CubeField[] measureRandomList= new Excel.CubeField[3];
Excel.CubeField[] dimensionRandomList = new Excel.CubeField[6];
for (int i = 0; i < 3; i++)
{
measureRandomList[i] = measureList[mesRan.Next(1, measureList.Count)];
}
for (int i = 0; i < 6; i++)
{
dimensionRandomList[i] = dimensionList[dimRan.Next(i, dimensionList.Count)];
}
for (int i = 0; i < 3; i++)
{
var field = measureRandomList[i];
var name = measureRandomList[i].Name;
field.Orientation= Excel.XlPivotFieldOrientation.xlDataField;
}
dimensionRandomList[0].Orientation= Excel.XlPivotFieldOrientation.xlRowField;
dimensionRandomList[1].Orientation = Excel.XlPivotFieldOrientation.xlColumnField;
dimensionRandomList[2].Orientation = Excel.XlPivotFieldOrientation.xlPageField;
dimensionRandomList[2].EnableMultiplePageItems=true;
//How can I get cubefield items list ?
}
You can filter your fields like this:
yourPivotField.CurrentPageName = string.Format("[{0}].[{1}].&[{2}]", SheetName, FieldName, FieldValue);
This sets the filter of your pivot table
Not sure if it it this you were searching for.
Related
If I want to add records to datagridview, it is okay, but I want to add records to the database which rows in datagridview.
There is a method - how am I adding Datagridview rows.
public void SepeteEkle()
{
decimal? tutar;
decimal? toplamtutar = 0;
int miktarsum = 0;
DataRow urun = dt.NewRow();
tutar = Convert.ToDecimal(lblFiyat.Text) * Convert.ToInt32(txtMiktar.Text);
bool itemfound = false;
for (int i = 0; i < dgvSepet.Rows.Count; i++)
{
if (Convert.ToString(dgvSepet.Rows[i].Cells[0].Value) == lblStokID.Text)
{
miktarsum += Convert.ToInt32(dgvSepet.Rows[i].Cells[4].Value) + Convert.ToInt32(txtMiktar.Text);
toplamtutar += Convert.ToDecimal(dgvSepet.Rows[i].Cells[5].Value) + tutar;
dgvSepet.Rows[i].Cells[4].Value = miktarsum;
dgvSepet.Rows[i].Cells[5].Value = toplamtutar;
itemfound = true;
}
}
if (itemfound == false)
{
urun["Id"] = lblStokID.Text;
urun["StokKodu"] = txtStokKodu.Text;
urun["Ürün"] = txtStokAdi.Text;
urun["Fiyat"] = lblFiyat.Text;
urun["Miktar"] = txtMiktar.Text;
urun["Toplam"] = tutar;
dt.Rows.Add(urun);
dgvSepet.DataSource = dt;
}
}
I want to add database this all created rows using Entity Framework.
What I tried:
public void DatabaseSepetAktar()
{
xstHar stokHareketModel = new xstHar();
stokHareketModel.stharCariKod = txtCariKodu.Text;
stokHareketModel.stharTarih = DateTime.Now;
stokHareketModel.stharDovFiyat = Convert.ToDecimal(lblTotal.Text);
for (int i = 0; i < dgvSepet.Rows.Count -1 ; i++)
{
stokHareketModel.masterId = Convert.ToInt32(dgvSepet.Rows[i].Cells[0].Value);
stokHareketModel.stokKodu = dgvSepet.Rows[i].Cells[1].Value.ToString();
stokHareketModel.stharGcMik1 = Convert.ToDecimal(dgvSepet.Rows[i].Cells[4].Value);
using (fastCellDb db = new fastCellDb())
{
db.xstHars.Add(stokHareketModel);
db.SaveChanges();
}
}
}
But I get an error
Validation exception
from Entity Framework.
How can I solve this problem ?
Validation exception raises when you try to convert value with wrong type, that is due to wrong indexing. As you add a row to your DataGridView dt.Rows.Add(urun) using text indexing, change the indexing way from number to text everywhere: Cells[0] → Cells["Id"] etc.
And look to the line: for (int i = 0; i < dgvSepet.Rows.Count -1 ; i++), it seems -1 is excess there.
Is there any way to use a LINQ style query to pass the Value of the highlighted Cells(without ComboBox) to another DataGridView? In the figure below, the cells to be transferred are marked.
Many thanks in advance for your ideas!
private void Button3_Click(object sender, EventArgs e)
{
for (int i = 0; i < dataGridView2.Rows.Count; i++)
{
for(int j = 0; j < dataGridView2.Columns.Count; j++)
{
if (!(dataGridView2.Rows[i].Cells[j].Value == null))
{
var cr =
dataGridView2.Rows[i].Cells[j].Style.BackColor =
Color.Red;
var cg =
dataGridView2.Rows[i].Cells[j].Style.BackColor =
Color.LawnGreen;
dataGridView3.Rows.Add(cr);
dataGridView3.Rows.Add(cg);
}
}
}
}
Ok, here's some sample code using linq which will copy values where a cell has a certain background color. The key to using Linq is the Cast method which can take non-generic IEnumerable and turn it into a generic IEnumerable so we can use the linq syntax. It also uses the Select overload which includes a parameter for the index, so you can easily index into the second data grid to get to the correct row / column.
var linqable = dataGridView2.Rows.Cast<DataGridViewRow>().Select((r, y) => new
{
row = r,
rowNum = y,
cells = r.Cells.Cast<DataGridViewCell>().Select((a, b) =>
new
{
cell = a,
cellNum = b
})
});
foreach(var row in linqable)
{
foreach(var cellWithRed in row.cells.Where(x => x.cell.Style.BackColor == Color.Red))
{
dataGridView3.Rows[row.rowNum].Cells[cellWithRed.cellNum].Value = cellWithRed.cell.Value;
}
}
Background/Context
I am currently building a function that will take a value and compare it against a list to find at which point the string values become bigger. The value I take is a date and the String contains a range of dates that are headings to a chart and essentially I am trying to find the column in excel where this date would fit in. The heading dates are all weekly dates. I've tried to get my logic around it but nothing seems to be working so thought I'd ask on here.
Logic Behind Code
The program creates a IEnumerable to find cell of records for which date we are looking up
The program creates a IEnumerable with all the dates in the headings.
The program takes that date and compares it to the IEnumerable in 2. to return a column where the new date will go.
Code up to point 2
List<string> Sheet1Rows = new List<string>();
List<string> Sheet2Rows = new List<string>();
List<DateTime> ColumnDates = new List<DateTime>();
//List<int> NewRowsNumber = new List<int>();
for (int row = 9; row <= LastRowSheet1; row++)
{
Sheet1Rows.Add(ExcelWksht1.Cells[row, 1].Value);
}
for (int row = 9; row <= LastRowSheet2; row++)
{
Sheet2Rows.Add(ExcelWksht2.Cells[row, 1].Value);
}
for (int column = 16; column <= LastColumnSheet2; column++)
{
ColumnDates.Add(ExcelWksht2.Cells[5, column].Value);
}
IEnumerable<string> Names1 = Sheet1Rows;
IEnumerable<string> Names2 = Sheet2Rows;
IEnumerable<DateTime> Dates1 = ColumnDates;
IEnumerable<string> NamesInBoth = Names1.Intersect(Names2);
IEnumerable<string> NamesOnlyInTwo = Names2.Except(Names1);
Debug.Print("NamesInBoth\n==========");
foreach (var n in NamesInBoth)
{
Debug.Print(n.ToString());
//Get Row Values
int rowinsheet1 = (Sheet1Rows.FindIndex(x => String.Compare(x, n) == 0)) + 9;
int rowinsheet2 = (Sheet2Rows.FindIndex(x => String.Compare(x, n) == 0)) + 9;
//Get Date Values
var Sheet1Date = ExcelWksht1.Cells[rowinsheet1, 9].Value.ToString();
var Sheet2Date = ExcelWksht2.Cells[rowinsheet2, 9].Value.ToString();
if (Sheet1Date != "No Planned Date" && Sheet2Date != "No Planned Date")
{
if (Sheet1Date != null && Sheet2Date != null)
{
if (Sheet1Date.ToString() != Sheet2Date.ToString())
{
//THIS IS WHERE IM STRUGGLING
}
}
else
{
((Excel.Range)ExcelWksht2.Cells[rowinsheet2, 1]).EntireRow.Interior.Color = Microsoft.Office.Interop.Excel.XlRgbColor.rgbOrange;
}
}
}
The Problem
As shown in the code I need to figure out a way to construct a loop (?) to check the row date value against all the heading values in the IEnumerable to give me the date value that begins the 7 day range.
I have the method here below. Before this method, I was getting the data from one table and now from two tables so I changed ListView as shown below.
Before using two different tables the ListView was designed at properties tab and all was working good.
The method below when writing items bypass the first column and begins from the second.
What is the bug ?
Any help will be very precious.
private void ShowPage()
{
// some declarations such count,LineNbr etc...
if (PublicVariables.PrintData == 1)
{
// seeting column headers and with and alignement if PrintData=1
newtmp = new string[5];
}
else
{
// seeting column headers and with and alignement if PrintData=2
newtmp = new string[7];
}
LineNbr = File.ReadAllLines(fName).Length;
ppc.View = View.Details;
ListViewItem DispItem = new ListViewItem();
while (counter < LineNbr && (line = streamToPrint.ReadLine()) != null)
{
string[] tmp = line.Split('|'); // Splitting the Data
sayac = 0;
for (int i = 0; i < tmp.Length; ++i)
{
if (tmp[i] != "")
{
newtmp[sayac] = tmp[i];
++sayac;
}
}
for (int a=0; a<newtmp.Length; ++a) // I add to SubItems
DispItem.SubItems.Add(newtmp[a]);
ppc.Items.AddRange(new ListViewItem[] {DispItem}); // I pass to ListView ppc
if (PublicVariables.PrintData == 1) //Initialise newtmp string
newtmp = new string[5];
else
newtmp = new string[7];
DispItem = new ListViewItem(); // Initialiase ListViewItem
++counter;
}
}
for (int a=0; a<newtmp.Length; ++a) // I add to SubItems
DispItem.SubItems.Add(newtmp[a]);
ppc.Items.AddRange(new ListViewItem[] {DispItem}); // I pass to Lis
Instead of those lines above, I have to do as below :(
DispItem = new ListViewItem(newtmp);
ppc.Items.Add(DispItem);
I was trying everything to resolve this.
After all, my excuses for those who give mind
I have a GridView with CheckBoxes and I wish to retrieve Cell[1] in every row that was checked. The list always end up being 'null'. The code is below. I added a string to display the output and that works fine. So I'm probably Adding it incorrectly but I don't know what. Any help would be appreciated. Cheers~
List<int> indices = new List<int>();
CheckBox cb = new CheckBox();
string text = "";
foreach (GridViewRow row in GV0.Rows)
{
if (((CheckBox)row.FindControl("CheckBox1")).Checked)
{
text += row.Cells[1].Text;
indices.Add(int.Parse(row.Cells[1].Text));
}
}
Label1.Text = text;
Session["indicesList"] = indices;
Response.Redirect("About.aspx");
The code for the page that is being redirected to:
List<List<string>> all = new List<List<string>>();
List<string> fields = new List<string>();
List<Type> fieldtypes = new List<Type>();
List<int> indices = new List<int>();
int show = 0;
if (!Page.IsPostBack)
{
all = (List<List<string>>)Session["all"];
fields = (List<string>)Session["fields"];
fieldtypes = (List<Type>)Session["fieldtypes"];
indices = (List<int>)Session["indiceslist"];
show = (int)Session["show"];
}
int j = 0;
List<List<string>> dupes = new List<List<string>>();
for (int i = 0; i < show; i++)
{
if (j < indices.Count)
{
if (int.Parse(all[i][0]) == indices[j])
{
dupes.Add(all[i]);
j++;
}
}
}
You're setting your list in the session with a key of indicesList but you're retrieving it with a key of indiceslist (Note the difference in case on the letter "L").
I would suggest creating a property for your list that gets and sets from the session. It makes it much easier to manage.
public List<int> Indices
{
get
{
var val = Session["indicesList"] as List<int>;
if(val == null)
{
val = new List<int>();
Session["indicesList"] = val;
}
return val;
}
set
{
Session["indicesList"] = value;
}
}