|
Thanks for the links...Let me try to clear the problem a little more:
InvReport is the main report which contain a subreport. Which is based on DataSet1.xsd contains 2 Tables rptOrders and rptOrderdetails
DataSet ds = Ord.GetOrdersByID(int.Parse(this.txtOrdID.text.ToString()));
Above line call the GetOrdersByID method of Orders class which return Dataset consist of 2 tables Orders and OrderDetails.
Then on a Print Button click event of Invoice form create an instance of InvReport invR, and set SetDataSource of invR to ds.Tables[0]. Lastly I called CrystalReportViewer.Report source to invR.
The problem is how can I "tell" SubReport to use ds.Tables[1] as SetDataSource. So that it can pick OrderDetails relevant to Orders data.
I hope I didn't make my problem more confusing...
Thanks
Ahmed
|
|
|
|
|
|
Thanks for the links, I will try to follow guidelines from both..
Appreciate your help.
regards
Ahmed
|
|
|
|
|
I have made code that iterates through a XpsDocument (fixeddocument). It will change the text of glyphs when certains criteria is matched. In visual studio I can see that the UnicodeString is changed. When I close the document the changes are not saved.
public bool Parse(params object[] args)
{
if ((args.Length > 0) && (args[0] is Dictionary<String, object>))
{
_values = args[0] as Dictionary<String, object>;
File.Copy(SourcePath, DestinationPath);
XpsDocument source = new XpsDocument(SourcePath, FileAccess.ReadWrite);
XpsDocument destination = new XpsDocument(DestinationPath,FileAccess.ReadWrite);
XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(destination);
FixedDocumentSequence sequence = destination.GetFixedDocumentSequence();
foreach (DocumentReference r in sequence.References)
{
FixedDocument d = r.GetDocument(false);
foreach (PageContent content in d.Pages)
{
ContainerVisual visual = new ContainerVisual();
FixedPage page = content.GetPageRoot(false);
double width = page.Width;
double height = page.Height;
Size size = new Size(page.Width, page.Height);
visual.Children.Add(page);
foreach(UIElement test in (page.Children[0] as Canvas).Children)
{
if (test is Glyphs)
{
String glyphContent = processGlyph(test as Glyphs);
}
if (test is Canvas)
{
Canvas address = test as Canvas;
foreach (UIElement row in address.Children)
{
if (row is Canvas)
{
String addres_text = processGlyph((row as Canvas).Children[0] as Glyphs);
}
}
}
}
}
}
source.Close();
destination.Close();
return true;
}
else
{
return false;
}
}
#endregion
#region Private Methods
private String processGlyph(Glyphs glyph)
{
String content="";
String glyphContent = (glyph as Glyphs).UnicodeString.Trim();
if ((glyphContent.StartsWith("«")) && (glyphContent.EndsWith("»")))
{
String key = glyphContent.Trim(new Char[] { '«', '»' });
if (_values.ContainsKey(key))
{
Glyphs item = (glyph as Glyphs);
content = item.UnicodeString.Replace(glyphContent, _values[key].ToString());
item.UnicodeString = content;
item.Indices = null;
}
else
{
Glyphs item = (glyph as Glyphs);
content = item.UnicodeString.Replace(glyphContent, "test");
item.UnicodeString = content;
item.ApplyTemplate();
}
}
return content;
}
Anyone has an idea on how to save the changes that were made to the glyphs?
|
|
|
|
|
I don't see anywhere in your code that you write the new data to the destination or writer objects.
Veni, vidi, abiit domum
|
|
|
|
|
Ok, that is correct, but then the question is how to write the changes back to the fixeddocument?
If I write to writer I will get a :
Package already has a root DocumentSequence or FixedDocument.
And I could not find a way to write it back to destination. Do you know how to do that?
|
|
|
|
|
I am not familiar with the XPS API so I would suggest you go back to the documentation to see what sequence is suggested.
Veni, vidi, abiit domum
|
|
|
|
|
Actually, that is the problem. I make some changes, but there is now way I could find that allows me to write the changes back to the file.
|
|
|
|
|
|
Yes, but it is a C++ library and my application is C# 
|
|
|
|
|
|
Good morning.
I have created a library of functions in C#, and I am testing them to see if they work in both VBA and on a spreadsheet (I am ok if they only work in VBA).
I have C# code to display the LastColumn and the LastRow in a spreadsheet as follows:
public string FindLastColumn(Worksheet xlWorkSheet)
{
int nInLastCol = 0;
nInLastCol = xlWorkSheet.Cells.Find("*", System.Reflection.Missing.Value, System.Reflection.Missing.Value,
System.Reflection.Missing.Value, XlSearchOrder.xlByColumns,XlSearchDirection.xlPrevious,
false,System.Reflection.Missing.Value,System.Reflection.Missing.Value).Column;
return GetExcelColumnName(nInLastCol);
}
private string GetExcelColumnName(int columnNumber)
{
int dividend = columnNumber;
string columnName = String.Empty;
int modulo;
while (dividend > 0)
{
modulo = (dividend - 1) % 26;
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
dividend = (int)((dividend - modulo) / 26);
}
return columnName;
}
public long FindLastRow(Worksheet xlWorkSheet)
{
long nInLastRow = 0;
nInLastRow = xlWorkSheet.Cells.Find("*", System.Reflection.Missing.Value,
System.Reflection.Missing.Value, System.Reflection.Missing.Value,
XlSearchOrder.xlByRows,XlSearchDirection.xlPrevious,
false,System.Reflection.Missing.Value,System.Reflection.Missing.Value).Row;
return nInLastRow;
}
The FindLastColumn code works in VBA, but the FindLastRow does not, and neither works on a sheet (not sure how to correctly pass in the current sheet). The error is: Function or interface marked as retricted, or the function uses an Automation type not supported in Visual Basic.
VBA:
Dim TSExcelLib As New TechSolutionsXLLibrary.ExcelFunctions
Private Sub CommandButton1_Click()
MsgBox TSExcelLib.FindLastColumn(Sheets("Sheet1")) 'Works
MsgBox TSExcelLib.FindLastColumn(Sheet1) 'Works
MsgBox TSExcelLib.FindLastColumn(Sheets("Sheet1")) 'Doesn't work
MsgBox TSExcelLib.FindLastColumn(Sheet1) 'Doesn't work
Any insight would be greatly appreciated. WHEELS
|
|
|
|
|
I'm not an Office dev, but is there any particular reason you wouldn't use worksheet.UsedRange() and just return the appropriate row or column value?
Or...Worksheets("name").Cells.SpecialCells(xlCellTypeLastCell).Row ?
|
|
|
|
|
It has been a while since I created the code, and I don't recall why I took that approach, but I can give the UsedRange 'method' a try. Thank you for your reply. WHEELS
|
|
|
|
|
The UsedRange in Excel is notoriously unreliable - if the cursor has been moved to a blank cell outside the range of your data, Excel often sets the UsedRange to that cell, meaniing that you can potentially end up by reading large numbers of blank rows when you don't need to
=========================================================
I'm an optoholic - my glass is always half full of vodka.
=========================================================
|
|
|
|
|
Quote: The FindLastColumn code works in VBA, but the FindLastRow does not, and neither works on a sheet (not sure how to correctly pass in the current sheet). The error is: Function or interface marked as retricted, or the function uses an Automation type not supported in Visual Basic
Just a stab in the dark, but you have defined FindLastRow as "long". The VBA "Long" integer is 32 bit versus the c# "long" which is a 64 bit integer.
|
|
|
|
|
I am currently working a project using wpf. I want a promptBox that will allow the user enter some information which will be use in the app. Eg i want he user to enter some setting information in the promptwindow
|
|
|
|
|
So, create a Window that will display the prompt and TextBox for the user to enter into, along with a couple of buttons to OK or Cancel. Have a ViewModel behind this that the View will bind to as the DataContext .
|
|
|
|
|
The csv file has only about 450 lines with 55 variables separated by commas . . but takes about 120 seconds to populate the DataViewGrid.
Since the csv file will be updated throughout the day and used as an input for the app, I need to speed this up considerably. It's the parsing that is taking the time. Any ideas greatly appreciated.
After reading the csv file to lines (string array) . . .
for (int x = 0; x >= lines.GetUpperBound(0); x++)
{
DataGridView1.Rows[x].SetValues(lines[x].Split(','));
}
|
|
|
|
|
Populating the grid directly is VERY slow. You should be loading the data in a DataTable and binding the grid to that instead.
|
|
|
|
|
Thanks Dave.
Do you have a source I can go to get the minimum code to populate the DGV?
I believe what I have found is overkill . . since I only need to populate the DGV . . no queries needed. I'm having trouble adding correct references. I added System.Web & following using statement:
using System.Web.Configuration;
I didn't think . . .
using System.Data.Odbc;
would be necessary to only populate the DGV file?
I have copied csv records into . .
string[] lines = system.IO.File.ReadAllLines("C:\\TaxLtrExport\\ClientInfoMaster.csv");
Trying to get references & code to populate the DGV.
Thanks for any suggestions.
John
|
|
|
|
|
Again, You have the lines from the CSV file. Parse them and put them into a DataTable object, then bind the DGV to the DataTable. No, I don't have code to give you.
Also, the DGV is a Windows Forms control. You don't need the System.Web namespaces at all.
|
|
|
|
|
Thanks for your input.
OK . . I have parsed the lines, adding them to a DataTable. I then bound to my DGV.
The time to populate the dgv decreased from 120 sec to 15 sec . . . nice improvement.
My program interacts with other DGVs and it is necessary to add rows to my DGV. Note that the program worked without using a DataTable, but was slow populating the data from the CSV file to the DGV. I have no problem with speed issues on other functions . . adding rows directly to the DGV, sorting, etc.
Now after using a DataTable as a data source for the DGV (only for populating the DGV) I get an error when other functions run to add rows to the DGV. I understand I could just work thru the bound DataTable, but I would prefer not. After I bound the data table to the dgv . . .
DataGridView1.DataSource = csvData; //csvData is DataTable
But when functions try to run that add rows to dgv,
DataGridView1.Rows.Add();
I get the error . . .
Rows cannot be programmatically added to the DataGridView's rows collection when the control is data-bound.
So I would like to use the datatable only to initially populate the dgv and then UNBIND, allowing the program to run as it did before, having resolved the speed issue in populating.
I have used the following attempting to unbind, but still get the same error above.
DataGridView1.DataBindings.Clear();
DataGridView1.Columns.Clear(); //NO . . this deletes ALL rows.
DataGridView1.DataSource.Equals(null);
Any suggestions would be appreciated.
John
|
|
|
|
|
Bound grids cannot have rows arbitrarily deleted from or added to them. You have to delete/add them from/to the source they are bound to.
You have a choice. Bind the grid and gain speed or don't bind the grid and loose the speed. There is no such thing as "bind and forget" the way you describe. Once you unbind the grid, it forgets about all the data that came across that binding.
I hear you asking "but I've seen rows being added to bound grids?". They're not adding the row to the grid. The grid is editing a blank row that was added to the source by the grid through a BindingNavigator.
The fastest your going to get is a databound grid that has Virtual mode turned on.
There is no such as Virtual mode when manually adding rows to an unbound grid. It only works with bound sources.
|
|
|
|
|
Appreciate your input . . . I understand. I also understand I may be in over my head. I'm not a programmer by profession . . I have written many programs related to my work as CPA tax planner & investment advisor. Of course, I would like to have a databound grid.
I have not bound anything before. Having a hard time getting head around it . . may have to start from scratch instead of trying to edit what I have. Hard to decide since what I have (unbound)works but is slow.
Basically, I have a master csv file that takes another csv file (generatded by a commercial tax program) and updates my master csv file. One question . . . my unbound program adds any new row (from small csv file) to master csv file. My changed program that now has a DGV bound to a datatable. Where I have added a row to my DGV . . . do I now change the coding to add a row to the datatable?
Dave, thanks again for your input. If you think I need to start over from scratch, can you suggest any tutorials that will help me get the concept (binding DGV - datatable in my head)?
|
|
|
|