I have a problem where I am trying to add images to a grid, but the images are being added oddly. (See Picture). I am trying to add the images in a straight row, yet they are being added in the first spot then in the next row. I am a noob, so I am very confused. Thank you for your help.
(The TUtils are just grabbing values from an .ini file)
Code:
private void PopulateGrid()
{
Image img = CreateImage();
ImageSize = TUtils.GetIniInt(Moleini, "ImageSize", "imageSize", 10);
NumofImages= TUtils.GetIniInt(Moleini, "NumPictures", "pictures", 8);
int ImageBorderSize = TUtils.GetIniInt(Moleini, "ImageBorder", "imageBorder", 2);
double NumberOfColumns = TUtils.GetIniInt(Moleini, "NumRowsColumns", "columnNum", 4);
// More Columns than Rows \\
if (NumberOfColumns > NumofImages)
{
MessageBox.Show("There is something wrong with the .ini file.");
MainWin.Close();
}
// Math - Get Necessary Variables \\
int ColumnSize = (ImageSize + (2 * ImageBorderSize));
int RowSize = (ImageSize + (2 * ImageBorderSize));
int NumberofRows = (int)Math.Ceiling(NumofImages / NumberOfColumns);
int MainWindowWidth = (TUtils.ToInt(NumberOfColumns.ToString(), 2) * ColumnSize) + 15;
int MainWindowHeight = (NumberofRows * RowSize) + 35;
// Set Window Size \\
MainWin.Width = MainWindowWidth;
MainWin.Height = MainWindowHeight;
// Create Grid \\
MainWin.Content = grid_Main;
grid_Main.Height = MainWindowHeight;
grid_Main.Width = MainWindowWidth;
grid_Main.Background = Brushes.Transparent;
// Grid Properties \\
for (int i = 0; i < NumberOfColumns; i++)
{
ColumnDefinition newColumn = new ColumnDefinition();
newColumn.Width = new GridLength(ColumnSize, GridUnitType.Pixel);
grid_Main.ColumnDefinitions.Add(newColumn);
}
for (int i = 0; i < NumberofRows; i++)
{
RowDefinition Row = new RowDefinition();
Row.Height = new GridLength(RowSize, GridUnitType.Pixel);
grid_Main.RowDefinitions.Add(Row);
}
// Fill Grid \\
int RowCount = 0;
int ColumnCount = 0;
for (int i = 0; i <= NumofImages; i++)
{
Image newImage = CreateImage();
if (RowCount < NumberofRows)
{
if (ColumnCount < NumberOfColumns)
{
Console.WriteLine("ColumnCount: " + ColumnCount.ToString());
Grid.SetRow(newImage, ColumnCount);
Grid.SetColumn(newImage, ColumnCount);
grid_Main.Children.Add(newImage);
ColumnCount++;
}
else
{
RowCount++;
ColumnCount = 0;
Grid.SetRow(newImage, ColumnCount);
Grid.SetColumn(newImage, ColumnCount);
grid_Main.Children.Add(newImage);
ColumnCount++;
Console.WriteLine("RowCount: " + RowCount.ToString());
}
}
else
{
break;
}
}
}
Discovers problem, I used "ColumnCount" when I should have used "RowCount"
Related
I am trying to get a total number of rows being used in excel using Epplus but I am unable to get an exact count and the count also includes null I need an only exact range of used cells.
these lines of code I am using
FileInfo fileinfo = new FileInfo(fileName);
ExcelPackage p = new ExcelPackage(fileinfo);
ExcelWorksheet w = p.Workbook.Worksheets[1];
int Rmax = w.Dimension.End.Row;
int Cmax = w.Dimension.End.Column;
Console.WriteLine(Rmax);
Console.WriteLine(Cmax);
You can get rows and columns from these lines
using (ExcelPackage package = new ExcelPackage(stream))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets[1];
int rowCount = worksheet.Dimension.Rows;
int colCount = worksheet.Dimension.Columns;
}
int count = Rmax * Cmax;
int firstCellValue = 0;
int lastCellValue = 0;
for (int row = 1; row <= Rmax; row++) {
for (int column = 1; column <= Cmax; column++) {
if (string.IsNullOrEmpty(worksheet.Cells[row, column].GetValue<String>())) {
count--;
}
}
}
UPDATE
int rowCount = Rmax;
int count = Rmax * Cmax;
string firstCellValue = string.Empty;
string lastCellValue = string.Empty;
for (int row = 1; row <= Rmax; row++) {
bool foundValue = false;
int leftIndex = 1;
int rightIndex = Cmax;
for (int column = 1; column <= Cmax; column++) {
if (leftIndex == rightIndex) {
if (!foundValue) {
rowCount--;
break;
}
}
if (!string.IsNullOrEmpty(worksheet.Cells[row, column].GetValue < String > ())) {
foundValue = true;
firstCellValue = worksheet.Cells[row, column].ToString();
leftIndex++;
}
if (!string.IsNullOrEmpty(worksheet.Cells[row, rightIndex].GetValue < String > ())) {
foundValue = true;
lastCellValue = worksheet.Cells[row, rightIndex].ToString();
rightIndex--;
}
}
}
Console.WriteLine("firstCellValue" + firstCellValue);
Console.WriteLine("lastCellValue" + lastCellValue);
Console.WriteLine("Number of cells" + rowCount);
I have just started working with EPPlus. i have data table which has some numeric data and formula. when i load data table by EPPlus and save to excel then formula not evaluated i found when i open the same excel file. formula lies in excel cell as string like SUM(A3:B3)
To evaluate formulate i have tried many options of EPPLUS and those are listed here
pack.Workbook.Worksheets["Test"].Calculate();
pack.Workbook.Worksheets["Test"].Cells["A3"].Calculate();
pack.Workbook.Worksheets["Test"].Cells["B3"].Calculate();
ws.Calculate();
Here i am referring my full sample code where formula not working. please have a look and tell me what i need to add in my code to evaluate formula.
private void button1_Click(object sender, EventArgs e)
{
DataTable dt = GetDataTable();
string path = #"d:\EPPLUS_DT_Excel.xlsx";
Stream stream = File.Create(path);
using (ExcelPackage pack = new ExcelPackage())
{
ExcelWorksheet ws = pack.Workbook.Worksheets.Add("Test");
ws.Cells["A1"].LoadFromDataTable(dt, false);
//pack.Workbook.Worksheets["Test"].Calculate();
//pack.Workbook.Worksheets["Test"].Cells["A3"].Calculate();
//pack.Workbook.Worksheets["Test"].Cells["B3"].Calculate();
ws.Calculate();
pack.SaveAs(stream);
stream.Close();
MessageBox.Show("Done");
}
}
public DataTable GetDataTable()
{
string strSum = "", strColName, strImmediateOneUp = "", strImmediateTwoUp = "";
int startsum = 0;
int currow = 0;
bool firstTimeSum = true;
int NumRows = 3;
int NumColumns = 2;
DataTable dt = new DataTable();
for (int col = 0; col < NumColumns; col++)
{
strColName = GenerateColumnText(col);
DataColumn datacol = new DataColumn(strColName, typeof(object));
dt.Columns.Add(datacol);
}
for (int row = 0; row < NumRows; row++)
{
dt.Rows.Add();
for (int col = 0; col < NumColumns; col++)
{
if (row < 2)
{
dt.Rows[row][col] = Convert.ToInt32(new Random().Next(1, NumRows));
}
else
{
if (firstTimeSum)
{
if (row - currow == 2)
{
currow = row;
startsum = 0;
firstTimeSum = false;
}
else
{
startsum = 1;
}
}
else
{
if (row - currow == 3)
{
currow = row;
startsum = 0;
}
}
if (startsum == 0)
{
strColName = GenerateColumnText(col);
strImmediateOneUp = strColName + ((row + 1) - 1).ToString();
strImmediateTwoUp = strColName + ((row + 1) - 2).ToString();
strSum = string.Format("+SUM({0}:{1})", strImmediateTwoUp, strImmediateOneUp);
dt.Rows[row][col] = strSum;
}
else
{
dt.Rows[row][col] = Convert.ToInt32(new Random().Next(1, NumRows));
}
}
}
startsum = 1;
}
return dt;
}
private string GenerateColumnText(int num)
{
string str = "";
char achar;
int mod;
while (true)
{
mod = (num % 26) + 65;
num = (int)(num / 26);
achar = (char)mod;
str = achar + str;
if (num > 0) num--;
else if (num == 0) break;
}
return str;
}
When adding a formula to a cell you use the Formula property. When you load a range from a DataTable using LoadFromDataTable it has no way of knowing that some of the values are meant to be interpreted as formulas.
You can use LoadDataTable to populate the cells on which the formulas will operate, but for the formulas you'll need to set the Formula property.
I have populated my data table with random values and formula like =SUM(A1:A2)
when there is 150 columns and 4000 rows in datatable then ReoGrid taking approx 20 minute to be populated.
when i am populating ReoGrid without formula then it takes few second to populate ReoGrid but the moment many SUM formulas are being assigned to cell dynamically then ReoGrid take long time to populated.
Here i am sharing my code. so my request please guys see my code logic and tell me is there any flaw when assigning formula to many cell of ReoGrid.
please tell me how could i simplify the logic to populate grid with formula. Is there way to increase the performance of my code with formula as a result ReoGrid can be populated with in few sec or few minute.
Looking for suggestion and guide line. ReoGrid is free component for winform application https://reogrid.net/.
Here is my code
private void btnBindTable_Click(object sender, EventArgs e)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
string strSum = "", strColName, strImmediateOneUp = "", strImmediateTwoUp = "";
int startsum = 0;
int currow = 0;
bool firstTimeSum = true;
int NumRows = 4000;
int NumColumns = 150;
var sheet = reoGrd.CurrentWorksheet;
sheet.Resize(NumRows, NumColumns); // resize
DataTable dt = new DataTable();
for (int col = 0; col < NumColumns; col++)
{
strColName = GenerateColumnText(col);
DataColumn datacol = new DataColumn(strColName, typeof(string));
dt.Columns.Add(datacol);
}
for (int row = 0; row < NumRows; row++)
{
dt.Rows.Add();
for (int col = 0; col < NumColumns; col++)
{
if (row < 2)
{
dt.Rows[row][col] = new Random().Next(1, NumRows).ToString("D2");
}
else
{
if (firstTimeSum)
{
if (row - currow == 2)
{
currow = row;
startsum = 0;
firstTimeSum = false;
}
else
{
startsum = 1;
}
}
else
{
if (row - currow == 3)
{
currow = row;
startsum = 0;
}
}
if (startsum == 0)
{
strColName = GenerateColumnText(col);
strImmediateOneUp = strColName + ((row + 1) - 1).ToString();
strImmediateTwoUp = strColName + ((row + 1) - 2).ToString();
dt.Rows[row][col] = strSum;
string cellname = GenerateColumnText(col) + (row + 1).ToString();
var cell = sheet.Cells[cellname];
cell.Style.BackColor = Color.LightGoldenrodYellow;
}
else
{
dt.Rows[row][col] = new Random().Next(1, NumRows).ToString("D2");
}
}
}
startsum = 1;
}
sheet["A1"] = dt;
stopwatch.Stop();
TimeSpan timeSpan = stopwatch.Elapsed;
MessageBox.Show(string.Format("Time elapsed: {0}h {1}m {2}s {3}ms", timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds, timeSpan.Milliseconds));
}
First of all, I'm a rookie in programming and I'm not English, I'm sorry if I had a mistake expressing myself :D
I'm doing a program that represents a booking system bus. I had created 64 buttons at Runtime with an array of buttons, but that isn't the problem.
The problem is to represent each text button corresponding to the number of seats of the bus. Here is my code:
var buttonArray = new Button[64];
for (var i = 1; i <= 4; i++)
{
buttonArray[i] = new Button();
buttonArray[i].Size = new Size(75, 23);
buttonArray[i].Name = "button" + i;
buttonArray[i].Text = "Seat " + i;
buttonArray[i].Location = new Point(-50 + (i*100), 10);
panel1.Controls.Add(buttonArray[i]);
for (var j = 5; j <= 19; j++)
{
buttonArray[j] = new Button();
buttonArray[j].Size = new Size(75, 23);
buttonArray[j].Name = "button" + j;
buttonArray[j].Text = "Seat " + j;
buttonArray[j].Location = new Point(-50 + (i * 100), -105 + (j * 30));
panel1.Controls.Add(buttonArray[j]);
}
}
The result would be 64 buttons represented with 4 columns and 16 rows, for example:
Here's how I would do it: Just loop from zero to 63, and calculate the row and column on the fly. Then you set the button properties and add it to the panel. You can change the size of the seats by adjusting the seatWidth and seatHeight variables. Also note that I added a little extra space between the first two columns and the second two columns, because it looks like that's what you had in your diagram. You can adjust this with the middleRowWidth variable. You can also customize the distance between the seats by adjusting the seatSpacing value:
const int seatSpacing = 4;
const int middleRowWidth = 20;
const int seatWidth = 55;
const int seatHeight = 20;
panel1.Width = 4 * (seatWidth + seatSpacing) + seatSpacing + middleRowWidth;
var buttonSize = new Size(seatWidth, seatHeight);
for (var i = 0; i < 64; i++)
{
// Calculate the location for this seat
int thisRow = i / 4;
int thisColumn = i % 4;
int seatTop = thisRow * (seatHeight + seatSpacing);
int seatLeft = thisColumn * (seatWidth + seatSpacing);
// Add some extra distance down the middle
if (thisColumn >= 2) seatLeft += middleRowWidth;
// Create a new button
var thisButton = new Button
{
Size = buttonSize,
Name = "button" + (i + 1),
Text = "Seat " + (i + 1),
Location = new Point(seatLeft, seatTop),
Visible = true,
};
// Add it to the panel
panel1.Controls.Add(thisButton);
}
Result:
UPDATE
After thinking about how to make this more generic, I thought about how some airplanes have their seats laid out. Some have two seats on each side, some have three, some have two on each side with a column of three down the middle. In order to accommodate different types of layouts, I modified the code slightly. Below code has customizable variables for your layout. The one below is for a 2-3-2 layout, where the numbers are the seat count and - are aisles. It also includes two "exit row" aisles running horizontally:
// Seating Layout
const int numberOfRows = 20;
const int numberOfColumns = 7;
const int numberOfSeats = numberOfRows * numberOfColumns;
var columnsToInsertAisleAfter = new List<int> {1, 4};
var rowsToInsertAisleAfter = new List<int> {6, 12};
// Seat sizing
const int seatWidth = 35;
const int seatHeight = 20;
const int seatSpacing = 4;
const int aisleWidth = 20;
var seatSize = new Size(seatWidth, seatHeight);
// Panel and form layout
panel1.Size = new Size(
numberOfColumns * (seatWidth + seatSpacing) + seatSpacing +
aisleWidth * columnsToInsertAisleAfter.Count,
numberOfRows * (seatHeight + seatSpacing) + seatSpacing +
aisleWidth * rowsToInsertAisleAfter.Count);
this.Size =
new Size(panel1.Size.Width + (panel1.Left * 2),
panel1.Size.Height + (panel1.Top * 2)) +
new Size(this.Width - this.ClientSize.Width,
this.Height - this.ClientSize.Height);
// Add seats to panel
for (var i = 0; i < numberOfSeats; i++)
{
// Calculate the location for this seat
int thisRow = i / numberOfColumns;
int thisColumn = i % numberOfColumns;
int seatTop = thisRow * (seatHeight + seatSpacing);
int seatLeft = thisColumn * (seatWidth + seatSpacing);
// Add some extra distance for aisles
var aislesBeforeThisColumn =
columnsToInsertAisleAfter.Count(col => col < thisColumn);
seatLeft += aislesBeforeThisColumn * aisleWidth;
var aislesBeforeThisRow =
rowsToInsertAisleAfter.Count(row => row < thisRow);
seatTop += aislesBeforeThisRow * aisleWidth;
// Add a new button to the panel
panel1.Controls.Add(new Button
{
Size = seatSize,
Name = "button" + (i + 1),
Text = (i + 1).ToString(),
Location = new Point(seatLeft, seatTop),
Visible = true,
});
}
Large Airplane Layout:
This should do what you want,
Point pt;
int y = 20;
int x = 0;
for (int i = 0; i < 16; i++)
{
x = 20;
for (int j = 1; j <= 4; j++)
{
pt = new Point(x, y);
Button btn = new Button() { Location = pt, Size = new Size(75, 23) };
btn.Name = i.ToString() + j.ToString();
btn.Text = string.Format("{0} {1:D2}", "Seat", i * 4 + j);
panel1.Controls.Add(btn);
x += 90;
}
y += 30;
}
I am trying to make a counter using an array that I used when I created several images, after a certain amount of time the image should disappear if it is not clicked, I am new to C#, and I am very confused. I think I have it for the most part, but it does not seem to work, thanks. In the code I include the two methods that use this array, CreateImage() which creates the "Mole" image, then adds it to a random spot on the grid, and deleteMole() where I am trying to delete this mole after 4 seconds.
Code:
private void ChangeImage()
{
string Moleimage = TUtils.GetIniFileString(Moleini, "ImagePath", "PictureFile", Root + "mole2.png");
NumofImages = TUtils.GetIniInt(Moleini, "NumPictures", "pictures", 8);
String MoleImageFunction = TUtils.GetIniFileString(Moleini, "ImagePath", "PictureFile", Root + "mole2.png");
for (int j = 0; j > NumofImages; j++)
{
ListArray[j]++;
}
Image newImage = HoleImage();
molePopup = MoleImage();
int numCol = Convert.ToInt32(NumberOfColumns);
int ranCol = randomColumns.Next(1, numCol);
int ranRow = randomRow.Next(1, NumberofRows);
Image mole = new Image();
//for (int i = 0; i < NumofImages; i++)
//{
mole.Source = new BitmapImage(new Uri(MoleImageFunction));
mole.Name = "Mole" + ListArray;
mole.Width = ImageSize;
mole.Height = ImageHeight;
//}
Grid.SetColumn(mole, ranCol);
Grid.SetRow(mole, ranRow);
grid_Main.Children.Add(mole);
//Calling MoileLifeCounter for Mole Death
moleLifeCounter();
mole.MouseUp += new MouseButtonEventHandler((o, e) =>
{
grid_Main.Children.Remove(mole);
MolePoints++;
});
}
private void deleteMole()
{
NumofImages = TUtils.GetIniInt(Moleini, "NumPictures", "pictures", 8);
int NumberofImages;
NumberofImages = Convert.ToInt32(NumofImages);
for (int j = 0; j > NumofImages; j++)
{
ListArray[j]--;
if (ListArray[j] == 0)
{
int numCol = Convert.ToInt32(NumberOfColumns);
int ranCol = randomColumns.Next(1, numCol);
int ranRow = randomRow.Next(1, NumberofRows);
Image newImage = HoleImage();
Grid.SetColumn(HoleImage(), ranCol);
Grid.SetRow(HoleImage(), ranRow);
grid_Main.Children.Add(HoleImage());
Console.WriteLine("TIMER WORKED!");
}
else
{
break;
}
}
}
looks to me like the loop which decrements the counter is never entered
for (int j = 0; j > NumofImages; j++) // wrong!
should be
for (int j = 0; j < NumofImages; j++)