C# Google Sheets API - Delete Row - c#

I searched everything already on the whole internet :) and did not find a solution for this.
I can add new rows, update old rows and do a lot of things in google sheets via C#, but I can't delete a row in a google sheet... can someone, please help me with this?
[EDITED]
OK, I finally found how to delete the rows...
So, what I had to do was first to build list of all indexes that are to be deleted. After doing that I had to build list of key pairs values with start and end of the index to delete, BUT for the end I had to add +1, as it seems like starts and ends are not deleted, only things that are between..
Finally I had to loop the list of key pairs from the end till the start and this deleted the rows...
The code to delete is here. Maybe this will help someone else who is looking how to delete rows in google sheets:
List<KeyValuePair<int, int>> _listStartEndIndexToDelete = new List<KeyValuePair<int, int>>();
List<int> _tempListOfAllIndex = new List<int>();
for (int i = 1; i <= ValuesInternal.Values.Count() - 1; i++)
{
if (ValuesInternal.Values[i][1] != null && ValuesInternal.Values[i][1].ToString().ToUpper() == "TASK COMPLETE")
{
_tempListOfAllIndex.Add(i);
}
}
for (int rowNumber = 0; rowNumber <= _tempListOfAllIndex.Count() - 1; rowNumber++)
{
int tempStart = _tempListOfAllIndex[rowNumber];
if(rowNumber != _tempListOfAllIndex.Count() - 1)
{
while (_tempListOfAllIndex[rowNumber] + 1 == _tempListOfAllIndex[rowNumber + 1])
{
rowNumber++;
if (rowNumber == _tempListOfAllIndex.Count() - 1) { break; }
}
}
int tempEnd = _tempListOfAllIndex[rowNumber] + 1;
KeyValuePair<int, int> tempPair = new KeyValuePair<int, int>(tempStart, tempEnd);
_listStartEndIndexToDelete.Add(tempPair);
}
for(int keyValuePair = _listStartEndIndexToDelete.Count()-1; keyValuePair >= 0; keyValuePair--)
{
List<Request> deleteRequestsList = new List<Request>();
BatchUpdateSpreadsheetRequest _batchUpdateSpreadsheetRequest = new BatchUpdateSpreadsheetRequest();
Request _deleteRequest = new Request();
_deleteRequest.DeleteDimension = new DeleteDimensionRequest();
_deleteRequest.DeleteDimension.Range = new DimensionRange();
_deleteRequest.DeleteDimension.Range.SheetId = SheetIDnumberWhereDeleteShouldBeDone;
_deleteRequest.DeleteDimension.Range.Dimension = "ROWS";
_deleteRequest.DeleteDimension.Range.StartIndex = _listStartEndIndexToDelete[keyValuePair].Key;
_deleteRequest.DeleteDimension.Range.EndIndex = _listStartEndIndexToDelete[keyValuePair].Value;
deleteRequestsList.Add(_deleteRequest);
_batchUpdateSpreadsheetRequest.Requests = deleteRequestsList;
sheetsService.Spreadsheets.BatchUpdate(_batchUpdateSpreadsheetRequest, SheetIDInternal).Execute();
}

I checked the links that You provided here, but non of them solved the problem.
For example this one:
Request request = new Request()
.setDeleteDimension(new DeleteDimensionRequest()
.setRange(new DimensionRange()
.setSheetId(0)
.setDimension("ROWS")
.setStartIndex(30)
.setEndIndex(32)
)
);
The problem is that, there is no such a thing like .setDeleteDimension under Request. This shouldn't be such a problem, but it is....
Below You can find my code. What does it do, is to take data from one sheet (internal) and put it to another sheet (internal archive). When this is done (and this works well), I want to delete data from internal as it is already archived... and that part is not working. I just don't know how to delete the rows.. if anyone could have a look on this, it would be great. Thanks for your help...
public void RunArchiveInternal2(bool testRun)
{
//internal
string SheetIDInternal = "googlesheetid_internal";
string RangeInternal = testRun ? "test_task tracking" : "Task Tracking - INTERNAL";
SpreadsheetsResource.ValuesResource.GetRequest getRequestInternal = sheetsService.Spreadsheets.Values.Get(SheetIDInternal, RangeInternal);
ValueRange ValuesInternal = getRequestInternal.Execute();
//internal archive
string SheetIDInternalArchive = "googlesheetid_internal_archive";
string RangeInternalArchive = testRun ? "test_archive_internal" : "Sheet1";
SpreadsheetsResource.ValuesResource.GetRequest getRequestInternalArchive = sheetsService.Spreadsheets.Values.Get(SheetIDInternalArchive, RangeInternalArchive);
ValueRange ValuesInternalArchive = getRequestInternalArchive.Execute();
//Get data from internal and put to internal archive
List<IList<object>> listOfValuesToInsert = new List<IList<object>>();
for (int i = 1; i <= ValuesInternal.Values.Count() - 1; i++)
{
List<object> rowToUpdate = new List<object>();
if (ValuesInternal.Values[i][1] != null && ValuesInternal.Values[i][1].ToString().ToUpper() == "TASK COMPLETE")
{
rowToUpdate = (List<object>)ValuesInternal.Values[i];
listOfValuesToInsert.Add(rowToUpdate);
}
}
SpreadsheetsResource.ValuesResource.AppendRequest insertRequest = sheetsService.Spreadsheets.Values.Append(new ValueRange { Values = listOfValuesToInsert }, SheetIDInternalArchive, RangeInternalArchive + "!A1");
insertRequest.ValueInputOption = SpreadsheetsResource.ValuesResource.AppendRequest.ValueInputOptionEnum.USERENTERED;
insertRequest.Execute();
//delete things from internal
BatchUpdateSpreadsheetRequest batchUpdateSpreadsheetRequest = new BatchUpdateSpreadsheetRequest();
List<DeleteDimensionRequest> requests = new List<DeleteDimensionRequest>();
for (int i = ValuesInternal.Values.Count() - 1; i >= 1; i--)
{
DeleteDimensionRequest request = new DeleteDimensionRequest();
//Request request = new Request();
if (ValuesInternal.Values[i][1] != null && ValuesInternal.Values[i][1].ToString().ToUpper() == "TASK COMPLETE")
{
request.Range = new DimensionRange
{
Dimension = "ROWS",
StartIndex = i,
EndIndex = i
};
requests.Add(request);
}
}
batchUpdateSpreadsheetRequest.Requests = requests;//this is wrong
SpreadsheetsResource.BatchUpdateRequest Deletion = sheetsService.Spreadsheets.BatchUpdate(batchUpdateSpreadsheetRequest, SheetIDInternal);
Deletion.Execute();
}

Related

How to insert to database in bulk instead of inserting it 1 by 1

How do you make the list receives more than 1 value based on the quantity of the SelectedList.Count.
Code:
for (int i = 0; i < SelectedList.Count; i++)
{
lastSeriesNo++;
string assetcodegen = string.Format("{0}-{1}-{2}", List[i].AssetCategoryID, CurrentApplication.Now.Year, lastSeriesNo.ToString().PadLeft(5, '0'));
AssetCodeOfficial[i] = assetcodegen;
var list = (from x in ctx.DataContext.AssetRegistryEntities
where x.AssetCode == SelectedList[i].AssetCode
select x
).AsEnumerable();
foreach (var asset in list)
{
asset.SeriesNumber = (short)lastSeriesNo;
asset.Status = 'A';
asset.IsTemp = false;
asset.UpdatedBy = CurrentApplication.CurrentUserId;
asset.UpdatedDate = asset.AssetCreatedDate = CurrentApplication.Now;
AssetCodetemp[i] = asset.AssetCode;
depreciationInMonths = asset.DepnInMonths;
ctx.DataContext.SubmitChanges();
}
}
Thank you all guys for the help, I manage to fix my problem. It already saves the data to the database as bulk not 1 by 1 saving.
So I use lambda expression for my list and use the .addRange to add item to the list.
list.AddRange(ctx.DataContext.AssetRegistryEntities.Where(x=>x.AssetCode.Trim() == SelectedList[i].AssetCode.Trim()));
Code:
List<NXpert.FixedAsset.DataAccess.AssetRegistryEntity> list = new List<NXpert.FixedAsset.DataAccess.AssetRegistryEntity>();
for (int i = 0; i < SelectedList.Count; i++)
{
lastSeriesNo++;
string assetcodegen = string.Format("{0}-{1}-{2}", List[i].AssetCategoryID, CurrentApplication.Now.Year, lastSeriesNo.ToString().PadLeft(5, '0'));
AssetCodeOfficial[i] = assetcodegen;
list.AddRange(ctx.DataContext.AssetRegistryEntities.Where(x=>x.AssetCode.Trim() == SelectedList[i].AssetCode.Trim()));
AssetCodetemp[i] = list[i].AssetCode;
}
foreach (var asset in list)
{
asset.SeriesNumber = (short)lastSeriesNo;
asset.Status = 'A';
asset.IsTemp = false;
asset.UpdatedBy = CurrentApplication.CurrentUserId;
asset.UpdatedDate = asset.AssetCreatedDate = CurrentApplication.Now;
depreciationInMonths = asset.DepnInMonths;
}
ctx.DataContext.SubmitChanges();

EP Plus - Error Table range collides with table

I am building an export to excel functionality using EP plus and c# application. I am currently getting the error.
'Table range collides with table tblAllocations29'
In my code logic below, I am looping through a data structure that contains key and collection as a value.
I looping across each key and once again loop through each collection belonging to that key.
I basically need to print tabular information for each collection along with its totals.
In the current scenario, I am getting the error when it is trying to print
three arrays
The first array has 17 records
The second array has 29 records
The third array has 6 records
I have taken a note of the ranges it is creating while debugging
The ranges are
A1 G18
A20 G50
A51 G58
controller
[HttpGet]
[SkipTokenAuthorization]
public HttpResponseMessage DownloadFundAllocationDetails(int id, DateTime date)
{
var ms = GetStrategy(id);
DateTime d = new DateTime(date.Year, date.Month, 1).AddMonths(1).AddDays(-1);
if (ms.FIRM_ID != null)
{
var firm = GetService<FIRM>().Get(ms.FIRM_ID.Value);
IEnumerable<FIRMWIDE_MANAGER_ALLOCATION> allocationsGroup = null;
var allocationsGrouped = GetAllocationsGrouped(EntityType.Firm, firm.ID, d);
string fileName = string.Format("{0} as of {1}.xlsx", "test", date.ToString("MMM, yyyy"));
byte[] fileContents;
var newFile = new FileInfo(fileName);
using (var package = new OfficeOpenXml.ExcelPackage(newFile))
{
FundAllocationsPrinter.Print(package, allocationsGrouped);
fileContents = package.GetAsByteArray();
}
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(fileContents)
};
result.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment")
{
FileName = fileName
};
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
return result;
}
return null;
#endregion
}
I have written the following utility that will try and export. It works sometimes when there are two array collections and it failed when processing three. Could somebody tell me what the problems are
FundsAllocationsPrinter.cs
public class FundAllocationsPrinter
{
public static void Print(ExcelPackage package, ILookup<string, FIRMWIDE_MANAGER_ALLOCATION> allocation)
{
ExcelWorksheet wsSheet1 = package.Workbook.Worksheets.Add("Sheet1");
wsSheet1.Protection.IsProtected = false;
int count = 0;
int previouscount = 0;
var position = 2;
int startposition = 1;
IEnumerable<FIRMWIDE_MANAGER_ALLOCATION> allocationGroup = null;
foreach (var ag in allocation)
{
allocationGroup = ag.Select(a => a);
var allocationList = allocationGroup.ToList();
count = allocationList.Count();
using (ExcelRange Rng = wsSheet1.Cells["A" + startposition + ":G" + (count + previouscount + 1)])
{
ExcelTableCollection tblcollection = wsSheet1.Tables;
ExcelTable table = tblcollection.Add(Rng, "tblAllocations" + count);
//Set Columns position & name
table.Columns[0].Name = "Manager Strategy";
table.Columns[1].Name = "Fund";
table.Columns[2].Name = "Portfolio";
table.Columns[3].Name = "As Of";
table.Columns[4].Name = "EMV (USD)";
table.Columns[5].Name = "Percent";
table.Columns[6].Name = "Allocations";
wsSheet1.Column(1).Width = 45;
wsSheet1.Column(2).Width = 45;
wsSheet1.Column(3).Width = 55;
wsSheet1.Column(4).Width = 15;
wsSheet1.Column(5).Width = 25;
wsSheet1.Column(6).Width = 20;
wsSheet1.Column(7).Width = 20;
// table.ShowHeader = true;
table.ShowFilter = true;
table.ShowTotal = true;
//Add TotalsRowFormula into Excel table Columns
table.Columns[0].TotalsRowLabel = "Total Rows";
table.Columns[4].TotalsRowFormula = "SUBTOTAL(109,[EMV (USD)])";
table.Columns[5].TotalsRowFormula = "SUBTOTAL(109,[Percent])";
table.Columns[6].TotalsRowFormula = "SUBTOTAL(109,Allocations])";
table.TableStyle = TableStyles.Dark10;
}
foreach (var ac in allocationGroup)
{
wsSheet1.Cells["A" + position].Value = ac.MANAGER_STRATEGY_NAME;
wsSheet1.Cells["B" + position].Value = ac.MANAGER_FUND_NAME;
wsSheet1.Cells["C" + position].Value = ac.PRODUCT_NAME;
wsSheet1.Cells["D" + position].Value = ac.EVAL_DATE.ToString("dd MMM, yyyy");
wsSheet1.Cells["E" + position].Value = ac.UsdEmv;
wsSheet1.Cells["F" + position].Value = Math.Round(ac.GroupPercent,2);
wsSheet1.Cells["G" + position].Value = Math.Round(ac.WEIGHT_WITH_EQ,2);
position++;
}
position++;
previouscount = position;
// position = position + 1;
startposition = position;
position++;
}
}
}
This is how the data looks when it is displayed successfully
Your issue is entirely in your Print method. You've been bitten by creating a slightly over-complicated row tracking mechanism and combining that with magic numbers. This causes you to position each table after the first one row higher than it should be. The header and subtotals are not part of the table, so you have a couple rows of leeway for the error. Tables can't overlap as you've seen, so EPPlus starts barking at you after you've exhausted your leeway.
All you need to do is keep track of the current row that you are writing to, and account for the space taken by your table header and footer (the subtotals) if you use them.
You declare these:
int count = 0;
int previouscount = 0;
var position = 2;
int startposition = 1;
But to write to the correct row, all you need is this:
var rowNumber = 1;
This will properly start writing your data in row one of the Excel sheet. As you write your table rows, you'll track and increment only the rowNumber. But what about the header and footer of each table? If you start writing at the first row of your table you'll overwrite the header, and if you don't account for both the header and footer you'll start having collisions like you've seen. So lets do this:
var showFilter = true;
var showHeader = true;
var showTotals = true;
var rowAdderForHeader = Convert.ToInt32(showHeader);
var rowAdderForFooter = Convert.ToInt32(showTotals);
These are pretty self explanatory, you'll use the rowAdders to hop the header or footer when needed. rowNumber will always be your current row to create your table and write your data. You use the count when defining your table, but we've made it irrelevant for anything else, so we move it:
var allocationList = allocationGroup.ToList();
//Moved here
var count = allocationList.Count();
Your using statement becomes:
using (ExcelRange Rng = wsSheet1.Cells["A" + rowNumber + ":G" + (count + rowNumber)])
Next, it isn't mentioned in your post, but you are going to run into a problem with the following:
ExcelTableCollection tblcollection = wsSheet1.Tables;
ExcelTable table = tblcollection.Add(Rng, "tblAllocations" + count);
Your table names have to be unique, but you could very well wind up with multiple allocations having the same count, which will cause EPPlus to throw an exception at you for duplicating a table name. So you'll want to also track the index of your current table:
var rowNumber = 1;
var tableIndex = 0;
//...
foreach (var ag in allocation)
{
tableIndex += 1;
//...
}
And use it to ensure unique table names:
ExcelTableCollection tblcollection = wsSheet1.Tables;
ExcelTable table = tblcollection.Add(Rng, "tblAllocations" + tableIndex);
We use our format control variables:
// table.ShowHeader = true;
table.ShowFilter = true;
table.ShowTotal = true;
//Changes to
table.ShowHeader = showHeader;
table.ShowFilter = showFilter;
table.ShowTotal = showTotals;
You have a small typo here:
table.Columns[6].TotalsRowFormula = "SUBTOTAL(109,Allocations])";
//Should be:
table.Columns[6].TotalsRowFormula = "SUBTOTAL(109,[Allocations])";
After you are done defining your table, you begin writing your data with a foreach loop. In order to prevent overwriting the table header if it exists, we'll have to advance one row. We also have to advance one row for each FIRMWIDE_MANAGER_ALLOCATION. If you are using the subtotals, we have to advance one row after the loop completes in order to properly position the next table:
rowNumber += rowAdderForHeader;
foreach (var ac in allocationGroup)
{
//...
rowNumber += 1;
}
rowNumber += rowAdderForFooter;
And that's it. We now properly track our position using just one variable, and we modify the position as necessary if there is a header or footer on your table.
The following is a complete working example that can be run in LinqPad as long as you add the EPPlus package through Nuget. It creates a random number of allocation groups each with a random number of allocations, and then exports them. Change the output file path to something that works for you:
void Main()
{
var dataGenerator = new DataGenerator();
var allocations = dataGenerator.Generate();
var xlFile = new FileInfo(#"d:\so-test.xlsx");
if (xlFile.Exists)
{
xlFile.Delete();
}
using(var xl = new ExcelPackage(xlFile))
{
FundAllocationsPrinter.Print(xl, allocations);
xl.Save();
}
}
// Define other methods and classes here
public static class FundAllocationsPrinter
{
public static void Print(ExcelPackage package, ILookup<string, FIRMWIDE_MANAGER_ALLOCATION> allocation)
{
ExcelWorksheet wsSheet1 = package.Workbook.Worksheets.Add("Sheet1");
wsSheet1.Protection.IsProtected = false;
IEnumerable<FIRMWIDE_MANAGER_ALLOCATION> allocationGroup = null;
var rowNumber = 1;
int tableIndex = 0;
var showFilter = true;
var showHeader = true;
var showTotals = true;
var rowAdderForHeader = Convert.ToInt32(showHeader);
var rowAdderForFooter = Convert.ToInt32(showTotals);
foreach (var ag in allocation)
{
tableIndex += 1;
Console.WriteLine(tableIndex);
allocationGroup = ag.Select(a => a);
var allocationList = allocationGroup.ToList();
var count = allocationList.Count();
using (ExcelRange Rng = wsSheet1.Cells["A" + rowNumber + ":G" + (count + rowNumber)])
{
ExcelTableCollection tblcollection = wsSheet1.Tables;
ExcelTable table = tblcollection.Add(Rng, "tblAllocations" + tableIndex);
//Set Columns position & name
table.Columns[0].Name = "Manager Strategy";
table.Columns[1].Name = "Fund";
table.Columns[2].Name = "Portfolio";
table.Columns[3].Name = "As Of";
table.Columns[4].Name = "EMV (USD)";
table.Columns[5].Name = "Percent";
table.Columns[6].Name = "Allocations";
wsSheet1.Column(1).Width = 45;
wsSheet1.Column(2).Width = 45;
wsSheet1.Column(3).Width = 55;
wsSheet1.Column(4).Width = 15;
wsSheet1.Column(5).Width = 25;
wsSheet1.Column(6).Width = 20;
wsSheet1.Column(7).Width = 20;
table.ShowHeader = showHeader;
table.ShowFilter = showFilter;
table.ShowTotal = showTotals;
//Add TotalsRowFormula into Excel table Columns
table.Columns[0].TotalsRowLabel = "Total Rows";
table.Columns[4].TotalsRowFormula = "SUBTOTAL(109,[EMV (USD)])";
table.Columns[5].TotalsRowFormula = "SUBTOTAL(109,[Percent])";
table.Columns[6].TotalsRowFormula = "SUBTOTAL(109, [Allocations])";
table.TableStyle = TableStyles.Dark10;
}
//Account for the table header
rowNumber += rowAdderForHeader;
foreach (var ac in allocationGroup)
{
wsSheet1.Cells["A" + rowNumber].Value = ac.MANAGER_STRATEGY_NAME;
wsSheet1.Cells["B" + rowNumber].Value = ac.MANAGER_FUND_NAME;
wsSheet1.Cells["C" + rowNumber].Value = ac.PRODUCT_NAME;
wsSheet1.Cells["D" + rowNumber].Value = ac.EVAL_DATE.ToString("dd MMM, yyyy");
wsSheet1.Cells["E" + rowNumber].Value = ac.UsdEmv;
wsSheet1.Cells["F" + rowNumber].Value = Math.Round(ac.GroupPercent, 2);
wsSheet1.Cells["G" + rowNumber].Value = Math.Round(ac.WEIGHT_WITH_EQ, 2);
rowNumber++;
}
//Account for the table footer
rowNumber += rowAdderForFooter;
}
}
}
public class FIRMWIDE_MANAGER_ALLOCATION
{
public FIRMWIDE_MANAGER_ALLOCATION(string name, Random rnd)
{
Name = name;
MANAGER_STRATEGY_NAME = "strategy name";
MANAGER_FUND_NAME = "fund name";
PRODUCT_NAME = "product name";
EVAL_DATE = DateTime.Now;
UsdEmv = (decimal)rnd.NextDouble() * 100000000;
GroupPercent = (decimal)rnd.NextDouble() * 100;
WEIGHT_WITH_EQ = 0;
}
public string Name { get; set; }
public string MANAGER_STRATEGY_NAME { get; set; }
public string MANAGER_FUND_NAME { get; set; }
public string PRODUCT_NAME { get; set; }
public DateTime EVAL_DATE { get; set; }
public decimal UsdEmv { get; set; }
public decimal GroupPercent { get; set; }
public decimal WEIGHT_WITH_EQ { get; set; }
}
public class DataGenerator
{
public static Random rnd = new Random();
public ILookup<string, FIRMWIDE_MANAGER_ALLOCATION> Generate()
{
var data = new List<FIRMWIDE_MANAGER_ALLOCATION>();
var itemCount = rnd.Next(1, 100);
for (var itemIndex = 0; itemIndex < itemCount; itemIndex++)
{
var name = Path.GetRandomFileName();
data.AddRange(GenerateItems(name));
}
return data.ToLookup(d => d.Name, d => d);
}
private IEnumerable<FIRMWIDE_MANAGER_ALLOCATION> GenerateItems(string name)
{
var itemCount = rnd.Next(1,100);
var items = new List<FIRMWIDE_MANAGER_ALLOCATION>();
for (var itemIndex = 0; itemIndex < itemCount; itemIndex++)
{
items.Add(new FIRMWIDE_MANAGER_ALLOCATION(name, rnd));
}
return items;
}
}

Displaying parsed csv files

Ive been working at this for hours and cant seem to figure out how to correctly display the data in a table
using (TextFieldParser csvParser = new TextFieldParser(path)) {
csvParser.CommentTokens = new string[] { "#" };
csvParser.SetDelimiters(new string[] { "," });
csvParser.HasFieldsEnclosedInQuotes = true;
csvParser.ReadLine();
int pointX = 30;
int pointY = 40;
while (!csvParser.EndOfData) {
string[] fields = csvParser.ReadFields();
int rowNums = fields.Length;
int index = 0;
for(index = 0; index < rowNums;index++) {
string Name = fields[index];
TextBox n = new TextBox();
n.Text = Name;
n.Location = new Point(pointX, pointY);
panel2.Controls.Add(n);
panel2.Show();
pointY += 20;
if(index != 0) {
pointX += 100;
}
}
}
}
Whats happening so far is im grabbing a csv file stored in the path variable and reading it the output is accessible through fields[] This works fine then I am trying to create textbox to put the data into based on rows however what i currently have comes out look like this
Program Display
I would like to display the column names and rows correctly in order here is an example image of what it looks like in notepad
Notepad Display
In notepad you will see each new line is a row and every , dictates a new entry in the row and i wanna display it this way in my program but in textbox
Also note that not all csv files that this program will be opening are short most will be large files with thousands or rows or more so theres no way that it could be simply putting fields[0] hard coded
You are much better off using a DataGridView to display this type of data in a table format.
From the toolbox add the DataGridView control to your form. You will need to build a DataTable that will bind to your DataGridview.
Below is what you can use(I commented out where you are skipping the header in your CSV file, and am using that line to get the column headers to be used in the datagrid)
var dt = new DataTable();
var lineNo = 0;
using (var csvParser = new TextFieldParser(path))
{
csvParser.CommentTokens = new string[] { "#" };
csvParser.SetDelimiters(new string[] { "," });
csvParser.HasFieldsEnclosedInQuotes = true;
//csvParser.ReadLine();
while (!csvParser.EndOfData)
{
var fields = csvParser.ReadFields();
var rowNums = fields.Length;
var row = dt.NewRow();
lineNo += 1;
int index = 0;
for (index = 0; index < rowNums; index++)
{
if (lineNo==1)
{
dt.Columns.Add(fields[index]);
}
else
{
row[index] = fields[index];
}
}
if (lineNo == 1) continue;
dt.Rows.Add(row);
dt.AcceptChanges();
}
}
dataGridView1.DataSource = dt;
I think the controls are overlapping, so you can not see them. That they are overlapping like chairs is the problem. You are not resetting your coordinates.
Here an improvement:
using (TextFieldParser csvParser = new TextFieldParser(path)) {
csvParser.CommentTokens = new string[] { "#" };
csvParser.SetDelimiters(new string[] { "," });
csvParser.HasFieldsEnclosedInQuotes = true;
csvParser.ReadLine();
int offsetX = 30;
int offsetY = 40;
int counter;
while (!csvParser.EndOfData) {
int pointerY = ++counter * offsetY; // first counter increments by one, then counter times offsetY occurs
int pointerX;
string[] fields = csvParser.ReadFields();
int rowNums = fields.Length;
for(int index = 0; index < rowNums;index++) {
pointerX = (index + 1) * offsetX;
string name = fields[index];
TextBox n = new TextBox() { Text = name, Location = new Point(pointerX, pointerY) };
panel2.Controls.Add(n);
panel2.Show(); // should be unnecessary
}
}
}

Make Code Fast Execute - replace For loops

It takes lot of time to execute these loops due to for loop implementation
How can I replace it to be more fast, the under laying table do not have much records too, plus I have made the primary keys too , but still the for loops are slow
public List<BusinessLayer.Transactions.CDANumberTracking> GetPOUnusedCDANumberTrackingItems(string code)
{
List<BusinessLayer.Transactions.CDANumberTracking> results = new List<BusinessLayer.Transactions.CDANumberTracking>();
List<Entity.Transactions.CDANumberTracking> SoUsedBagList = new List<Entity.Transactions.CDANumberTracking>();
List<Entity.Transactions.POCDANumberTracking> rejects = new List<SalesOrderModule.Entity.Transactions.POCDANumberTracking>();
List<Entity.Transactions.POCDANumberTracking> returns = new List<SalesOrderModule.Entity.Transactions.POCDANumberTracking>();
List<Entity.Transactions.POCDANumberTracking> rejectList = new List<SalesOrderModule.Entity.Transactions.POCDANumberTracking>();
List<Entity.Transactions.POCDANumberTracking> returnRejectList = new List<SalesOrderModule.Entity.Transactions.POCDANumberTracking>();
List<Entity.Transactions.POCDANumberTracking> SearchList = new List<SalesOrderModule.Entity.Transactions.POCDANumberTracking>();
try
{
if (!InOpenLookup)
(Connection as SQL).BeginTransaction();
DataLayer.Tables.PLSPOCDANumberTrackingDNew sampleTable = new SalesOrderModule.DataLayer.Tables.PLSPOCDANumberTrackingDNew(this.Connection);
sampleTable.SearchCriteria[0].Value = code.Trim();
sampleTable.SearchCriteria[1].Value = (int)0;
List<Entity.Transactions.POCDANumberTracking> results1 = sampleTable.Reads(false);
if (results1.Count > 0)
{
rejectList.AddRange(results1);
}
DataLayer.Tables.PLSPOCDANumberTrackingReturnD sampleTable2 = new SalesOrderModule.DataLayer.Tables.PLSPOCDANumberTrackingReturnD(this.Connection);
sampleTable2.SearchCriteria[0].Value = code.Trim();
List<Entity.Transactions.POCDANumberTracking> results2 = sampleTable2.Reads(false);
if (results2.Count > 0)
{
returnRejectList.AddRange(results2);
}
DataLayer.Tables.PLSPOCDANumberTrackingD sampleTable3 = new SalesOrderModule.DataLayer.Tables.PLSPOCDANumberTrackingD(this.Connection);
sampleTable3.SearchCriteria[0].Value = code.Trim();
SearchList = sampleTable3.Reads(false);
DataLayer.Tables.PSOMCDANumberTrackingD sampleTable4 = new SalesOrderModule.DataLayer.Tables.PSOMCDANumberTrackingD(this.Connection, null);
sampleTable4.SearchCriteria[3].Value = code.Trim();
sampleTable4.SearchCriteria[6].Value = false;
SoUsedBagList = sampleTable4.Read(false);
//process data...
Entity.Transactions.POCDANumberTracking temp;
foreach (Entity.Transactions.POCDANumberTracking rejectItem in rejectList)
{
for (int i = rejectItem.From; i <= rejectItem.To; i++)
{
temp = new SalesOrderModule.Entity.Transactions.POCDANumberTracking();
temp.From = i;
temp.To = i;
temp.Code = rejectItem.Code.Trim();
temp.GrnNo = rejectItem.GrnNo.Trim();
temp.WbcNo = rejectItem.WbcNo.Trim();
rejects.Add(temp);
}
}
//returns
foreach (Entity.Transactions.POCDANumberTracking returnItem in returnRejectList)
{
for (int i = returnItem.From; i <= returnItem.To; i++)
{
temp = new SalesOrderModule.Entity.Transactions.POCDANumberTracking();
temp.From = i;
temp.To = i;
temp.Code = returnItem.Code.Trim();
temp.GrnNo = returnItem.GrnNo.Trim();
temp.WbcNo = returnItem.WbcNo.Trim();
returns.Add(temp);
}
}
Entity.Transactions.CDANumberTracking temp2;
Entity.Transactions.CDANumberTracking temp3;
Entity.Transactions.POCDANumberTracking temp4;
foreach (Entity.Transactions.POCDANumberTracking searchItem in SearchList)
{
for (int i = searchItem.From; i <= searchItem.To; i++)
{
temp = null;
temp3 = null;
temp4 = null;
//check if the bag is on reject list
temp = rejects.Find(delegate(Entity.Transactions.POCDANumberTracking tc) { return (tc.From == i && tc.WbcNo.Trim().ToUpper() == searchItem.WbcNo.Trim().ToUpper() && tc.GrnNo.Trim().ToUpper() == searchItem.GrnNo.Trim().ToUpper()); });
if (temp != null)
continue;
//check if the bag is on return list
temp4 = returns.Find(delegate(Entity.Transactions.POCDANumberTracking tcc) { return (tcc.From == i && tcc.GrnNo.Trim().ToUpper() == searchItem.GrnNo.Trim().ToUpper()); });
if (temp4 != null)
continue;
//check if the bag is alredy used in So module...
temp3 = SoUsedBagList.Find(delegate(Entity.Transactions.CDANumberTracking cda) { return (cda.Code.Trim().ToUpper() == searchItem.Code.Trim().ToUpper() && cda.BagNo == searchItem.From); });
if (temp3 != null)
continue;
temp2 = new SalesOrderModule.Entity.Transactions.CDANumberTracking();
temp2.BagNo = i;
temp2.Code = searchItem.Code.Trim();
temp2.LineNo = 0;
temp2.Location = string.Empty;
temp2.WbcNo = string.Empty;
temp2.ID = null;
temp2.IsReturned = false;
temp2.IsSelected = false;
temp2.ItemNo = string.Empty;
temp2.Status = SalesOrderModule.Entity.ModifyStatus.New;
results.Add(BusinessLayer.Transactions.CDANumberTracking.GetCDANumberTracking(this, temp2, null));
}
}
if (!InOpenLookup)
(Connection as SQL).EndTransaction();
}
catch (Exception er)
{
if (!InOpenLookup)
(Connection as SQL).Rollback();
throw er;
}
return results;
}
the for loop under second for each need to placed ... need some help
You should factor out of the inner loop everything you can. As the code stands right now, you are unecessarily repeating the following operations:
returnItem.Code.Trim();
returnItem.GrnNo.Trim();
returnItem.WbcNo.Trim();
I have nowhere near enough information to judge if this will have any performance impact.
Other suspects are new SalesOrderModule.Entity.Transactions.POCDANumberTracking() and returns.Add(temp). If returns is somekind of ordered list, then this could have a considerable performance hit. If its a simple List then it shouldn't and there isn't much you could do to improve it anyways.
Concerning the constructor, only you know how expensive it is but there is not much you can do to avoid it either.
All that said, your code would look something like this:
Entity.Transactions.POCDANumberTracking temp;
foreach (Entity.Transactions.POCDANumberTracking returnItem in returnRejectList)
{
var code = returnItem.Code.Trim();
var grnNo = returnItem.GrnNo.Trim();
var wbcNo = returnItem.WbcNo.Trim();
for (int i = returnItem.From; i <= returnItem.To; i++)
{
temp = new SalesOrderModule.Entity.Transactions.POCDANumberTracking();
temp.From = i;
temp.To = i;
temp.Code = code;
temp.GrnNo = grnNo;
temp.WbcNo = wbcNo;
returns.Add(temp);
}
}
I have to limit the entries coming under the foreach loops, that is best way by debugging the code
so the data layer codes referring in the
sampleTable.Reads(false);
sampleTable2.Reads(false);
sampleTable3.Reads(false);
sampleTable4.Reads(false);
need to modified by including the Item for search (I mean the SQL STATEMENTS)

Index won't up of List

I'm still learning in programming
I'm trying to get customer data in list. So I can get the value from the index, but it only can get the first customer. the index won't increment, I'm still confusing, I have already move the variable for increment the index won't work, maybe my logic isn't right. here's the code, tell me where is not right..?? thank you for you help and explanation
public void getJamVSpot()
{
var listJamAwal = new List<String>();
var listJamAkhir = new List<String>();
var listNota = new List<int>();
DateTime tglSewa = dtp_tglSewa.Value.Date;
int r = 0;
String ja = String.Empty;
String jb = String.Empty;
int n = 0;
int indexUp = 0;
if (dtp_tglSewa.Value.Date == jl.getTglJadwalVspot(tglSewa, lap) && rdb_Lapangan_VSpot.Checked == true || rdb_rumputSintetis.Checked == true)
{
IEnumerator<String> jAwal = jl.getJamAwalbyDate(tglSewa, lap);
while (jAwal.MoveNext())
{
listJamAwal.Add(jAwal.Current);
}
IEnumerator<String> jAkhir = jl.getJamAkhirbyDate(tglSewa, lap);
while (jAkhir.MoveNext())
{
listJamAkhir.Add(jAkhir.Current);
}
IEnumerator<int> nota = jl.getNota(tglSewa, lap);
while (nota.MoveNext())
{
listNota.Add(nota.Current);
}
ja = listJamAwal[indexUp];
jb = listJamAkhir[indexUp];
n = listNota[indexUp];
int count = jl.countNota(n);
String penyewa = jl.getNamaPenyewa(n);
String no_kontak = jl.getNomorKontak(n);
String status = jl.getStatusSewa(n);
for (int i = 1; i <= count; i++)
{
foreach (DataGridViewRow row in dgv_Jadwal_Sewa.Rows)
if (row.Cells[0].Value.ToString().Equals(ja))
{
r = row.Index;
row.Cells[2].Value = penyewa;
row.Cells[3].Value = no_kontak;
row.Cells[4].Value = status;
if (ja != jb)
{
ja = jl.getJamAkhirbyJamAwal(ja);
row.Cells[2].Value = penyewa;
row.Cells[3].Value = no_kontak;
row.Cells[4].Value = status;
//dgv_Jadwal_Sewa.Rows[r].Selected = true;
}
break;
}
}
} indexUp++;
}
When you increment the indexUp variable you aren't using it anymore.
In your code you are just recovering the first item (0), doing some stuff with this value (in the loops) and exits.
For example, you can wrap your stuff with this loop:
for (int indexUp = 0; indexUp < listJamAwal.Count; indexUp++)
{
ja = listJamAwal[indexUp];
jb = listJamAkhir[indexUp];
n = listNota[indexUp];
int count = jl.countNota(n);
String penyewa = jl.getNamaPenyewa(n);
String no_kontak = jl.getNomorKontak(n);
String status = jl.getStatusSewa(n);
for (int i = 1; i <= count; i++)
{
foreach (DataGridViewRow row in dgv_Jadwal_Sewa.Rows)
{
if (row.Cells[0].Value.ToString().Equals(ja))
{
r = row.Index;
row.Cells[2].Value = penyewa;
row.Cells[3].Value = no_kontak;
row.Cells[4].Value = status;
if (ja != jb)
{
ja = jl.getJamAkhirbyJamAwal(ja);
row.Cells[2].Value = penyewa;
row.Cells[3].Value = no_kontak;
row.Cells[4].Value = status;
//dgv_Jadwal_Sewa.Rows[r].Selected = true;
}
break;
}
}
}
}
There are two problems with how you access the items:
You assign the variables outside the loop. That will get the values that the index points to at that moment, and changing the index variable later doesn't change what's assigned to the variables. You have to assign the variables inside the loop, except the count variable of course which you need before the loop starts.
You are incrementing the indexUp variable after the loop, when you have no use for it any more. You have to put that inside the loop so that it can be used in the next iteration to read new values into the variables.
I dont see any point of using first loop with "i" and then second with foreach. Its totally wrong - you are doing the same thing "count" times!
You also need to change penyewa, no_kontak, status because you are using same values inside loop
And in addition, I have never seen so confusing and unclear variable naming, you should change it if you want some else to use it :D

Categories

Resources