How to Show Blank Image In Crystal report - c#

By Below Procedure I am Displaying Image to Crystal Report
First: I created a New Column ("Image") in a datatable of the dataset and change the DataType to System.Byte()
Second : Drag And drop this image Filed Where I want.
private void LoadReport()
{
frmCheckWeigher rpt = new frmCheckWeigher();
CryRe_DailyBatch report = new CryRe_DailyBatch();
DataSet1TableAdapters.DataTable_DailyBatch1TableAdapter ta = new CheckWeigherReportViewer.DataSet1TableAdapters.DataTable_DailyBatch1TableAdapter();
DataSet1.DataTable_DailyBatch1DataTable table = ta.GetData(clsLogs.strStartDate_rpt, clsLogs.strBatchno_Rpt, clsLogs.cmdeviceid); // Data from Database
DataTable dt = GetImageRow(table, "Footer.Jpg");
report.SetDataSource(dt);
crv1.ReportSource = report;
crv1.Refresh();
}
// By this Function I merge My Image data into dataTable
private DataTable GetImageRow(DataTable dt, string ImageName)
{
try
{
FileStream fs;
BinaryReader br;
if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + ImageName))
{
fs = new FileStream(AppDomain.CurrentDomain.BaseDirectory + ImageName, FileMode.Open);
}
else
{
// if photo does not exist show the Blank Space or Show Nothing
for (int i = 0; i < dt.Rows.Count; i++)
{
dt.Rows[i]["Image"] = DBNull.Value ;
}
return dt;
}
// initialise the binary reader from file streamobject
br = new BinaryReader(fs);
// define the byte array of filelength
byte[] imgbyte = new byte[fs.Length + 1];
// read the bytes from the binary reader
imgbyte = br.ReadBytes(Convert.ToInt32((fs.Length)));
for (int i = 0; i < dt.Rows.Count; i++)
{
dt.Rows[i]["Image"] = imgbyte;
}
br.Close();
// close the binary reader
fs.Close();
// close the file stream
}
catch (Exception ex)
{
// error handling
MessageBox.Show("Missing " + ImageName + " in application folder");
}
return dt;
// Return Datatable After Image Row Insertion
}
this Works Perfectly when I have Image on path but
I want to Show Empty- blank Space when user Not Give Image on Specify path,
But I get blank Square as per given Image with border how to remove it please help me ..

Use the suppress function from the report it self,
Right click on the image object >> format object >> Fill the check box near the word suppress then click on the formula on the right of suppress then add the formula you require some thing like:
ISNULL({Class;1.Img})

Related

Size of Image while storing it in database

I'm facing an odd problem regarding image size.
I've made a simple application which stores and retrieves images in a database. When I'm reading an image from the file, its size is in kB(kilobytes) and so is the length of the byte array.
There are two pictureboxes. pb1 for storing, and pb2 for loading.
My store() and load() methods are given below:
note: openConnState() and CloseConnState() are methods for closing and opening connections. And the byte[] img_byte and imgfilelength = 0 are defined publicly in the class.
Store:
private void StoreImage(string ChosenFile)
{
try
{
//MemoryStream ms = new MemoryStream();
//pb1.Image.Save(ms, ImageFormat.Jpeg);
//img_byte = new byte[ms.Length];
//ms.Position = 0;
//ms.Read(img_byte, 0, img_byte.Length);
FileInfo fileImage = new FileInfo(ChosenFile);
imgfilelength = fileImage.Length;
FileStream fs = new FileStream(ChosenFile, FileMode.Open, FileAccess.Read, FileShare.Read);
img_byte = new Byte[Convert.ToInt32(imgfilelength)];
int count, sum = 0;
while ((count = fs.Read(img_byte, 0, Convert.ToInt32(imgfilelength))) > 0)
{
sum += count;
}
//int byteread = fs.Read(img_byte, 0, Convert.ToInt32(imgfilelength));
fs.Close();
}
catch (Exception e)
{
throw e;
}
}
public void storetoDB()
{
OpenConnState(conn);
string str = "use db2 \n insert into TableImg(Image) \n values('" + img_byte + "')";
SqlCommand cmd = new SqlCommand(str, conn);
try
{
cmd.ExecuteNonQuery();
}
catch (Exception e)
{
throw e;
}
finally
{
CloseConnState(conn);
}
}
Load:
public void Loadimg()
{
try
{
pb2.Image = null;
byte[] getbyte = LoadImagefromDB(3);
using (MemoryStream ms = new MemoryStream(getbyte))
{
pb2.Image = Image.FromStream(ms);
}
pb2.Refresh();
}
catch (Exception e)
{
throw e;
}
}
public byte[] LoadImagefromDB(long pid)
{
byte[] img = null;
OpenConnState(conn);
string str = "use db2 \n select Image from TableImg where P_Id = " + pid;
SqlCommand cmd = new SqlCommand(str, conn);
try
{
img = (byte[])cmd.ExecuteScalar();
return img;
}
catch (System.Exception e)
{
throw e;
}
finally
{
CloseConnState(conn);
}
}
I store the image into a database using the storeDB() method given above, but when I retrieve the image using the load() method given above, I get an error saying parameter invalid. I found out the problem is likely to be related to the length of the byte array, because when I retrieve the 'image' datatype value of database into a byte array, the length of byte array will always be 13.
And I even ran the below query to get its size in database, it is still the same, i.e. 13 bytes.
select len(Convert(varbinary(max), Image)) from TableImg where P_Id = 1
Can anyone tell me, why?
I retrieve the 'image' datatype value of database into a byte array,
the length of byte array will always be 13.
You are trying to do this:
use db2 \n insert into TableImg(Image) \n values('System.Byte[]')
obviously, length of the string System.Byte[] will always be 13.
You have to convert that binary data to other type before insert.
According to this post if your image is quite small in bytes, you can store it as VARBINARY type. If it big, you should store it as a file in the drive.
EDIT
You can use like this:
using (SqlCommand cmd = new SqlCommand("use db2 \n insert into TableImg(Image) \n values(#binaryValue)", conn))
{
cmd.Parameters.Add("#binaryValue", SqlDbType.VarBinary, img_byte.Length).Value = img_byte;
cmd.ExecuteNonQuery();
}

How to import large amounts of data from CSV file to DataGridView efficiently

I have 300 csv files that each file contain 18000 rows and 27 columns.
Now, I want to make a windows form application which import them and show in a datagridview and do some mathematical operation later.
But, my performance is very inefficiently...
After search this problem by google, I found a solution "A Fast CSV Reader".
(http://www.codeproject.com/Articles/9258/A-Fast-CSV-Reader)
I'm follow the code step by step, but my datagridview still empty.
I don't know how to solve this problem.
Could anyone tell me how to do or give me another better way to read csv efficiently.
Here is my code...
using System.IO;
using LumenWorks.Framework.IO.Csv;
private void Form1_Load(object sender, EventArgs e)
{
ReadCsv();
}
void ReadCsv()
{
// open the file "data.csv" which is a CSV file with headers
using (CachedCsvReader csv = new
CachedCsvReader(new StreamReader("data.csv"), true))
{
// Field headers will automatically be used as column names
dataGridView1.DataSource = csv;
}
}
Here is my input data:
https://dl.dropboxusercontent.com/u/28540219/20130102.csv
Thanks...
The data you provide contains no headers (first line is a data line). So I got an ArgumentException (item with same key added) when I tried to add the csv reader to the DataSource. Setting the hasHeaders parameter in the CachCsvReader constructor did the trick and it added the data to the DataGridView (very fast).
using (CachedCsvReader csv = new CachedCsvReader(new StreamReader("data.csv"), false))
{
dataGridView.DataSource = csv;
}
Hope this helps!
You can also do like
private void ReadCsv()
{
string filePath = #"C:\..\20130102.csv";
FileStream fileStream = null;
try
{
fileStream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
}
catch (Exception ex)
{
return;
}
DataTable table = new DataTable();
bool isColumnCreated = false;
using (StringReader reader = new StringReader(new StreamReader(fileStream, Encoding.Default).ReadToEnd()))
{
while (reader.Peek() != -1)
{
string line = reader.ReadLine();
if (line == null || line.Length == 0)
continue;
string[] values = line.Split(',');
if(!isColumnCreated)
{
for(int i=0; i < values.Count(); i++)
{
table.Columns.Add("Column" + i);
}
isColumnCreated = true;
}
DataRow row = table.NewRow();
for(int i=0; i < values.Count(); i++)
{
row[i] = values[i];
}
table.Rows.Add(row);
}
}
dataGridView1.DataSource = table;
}
Based on you performance requirement, this code can be improvised. It is just a working sample for your reference.
I hope this will give some idea.

Save & retrieve multiple image byte[] code in datagridview to SQL Server using XML C#

I am creating first one data table to save images in datagridview.
DataTable dt = new DataTable();
dt.Columns.Add("Name", typeof(string));//0
dt.Columns.Add("Upload", typeof(string));//1
dt.Columns.Add("Show", typeof(string));//2
dt.Columns.Add("image", typeof(byte[]));//3
for (int i = 0; i < dgvDemo.RowCount-1; i++)
{
DataRow drOLD = dt.NewRow();
drOLD["image"] =dgvDemo.Rows[i].Cells[3].Value;
drOLD["Name"] = dgvDemo.Rows[i].Cells[0].Value;
drOLD["Upload"] = "Upload";
drOLD["Show"] = "Show";
dt.Rows.Add(drOLD);
}
Image img = PBImage.Image; //Image.FromFile(#"physical path to the file");
DataRow dr = dt.NewRow();
dr["image"] = imageToByteArray(img);
dr["Name"] = "Image";
dr["Upload"] = "Upload";
dr["Show"] = "Show";
dt.Rows.Add(dr);
dgvDemo.DataSource = dt;
public byte[] imageToByteArray(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
This is the code saving images in database using XML as parameter for stored procedure
hash = new Hashtable();
hash.Add("#QueryNo", QueryNo);
string strXmlCategory_Section = "";
StringBuilder xmlClassMaster = new StringBuilder();
for (int k = 0; k < dgvDemo.Rows.Count-1; k++)
{
xmlClassMaster.Append("<Row>");
xmlClassMaster.Append("<Name>" + dgvDemo.Rows[k].Cells[0].Value + "</Name>");
xmlClassMaster.Append("<GridImage><cdata>" + ((byte[])dgvDemo.CurrentRow.Cells[3].Value) + "</cdata></GridImage>");
xmlClassMaster.Append("</Row>");
}
if (xmlClassMaster.Length > 0)
{
xmlClassMaster.Append("</ImageInGrid>");
strXmlCategory_Section = "<ImageInGrid>" + Convert.ToString(xmlClassMaster);
}
hash.Add("#strImageInGrid", strXmlCategory_Section);
hash table is passing as parameter list to the stored procedure.
Stored procedure code:
Exec sp_xml_prepareDocument #DocHandle_ImageInGrid output, #strImageInGrid
select Name, GridImage
into #temp
from OPENXML (#DocHandle_ImageInGrid, '/ImageInGrid/Row',12)
with (
Name varchar(50) 'Name',
GridImage varbinary(max) 'GridImage'
)
insert into dbo.GridImage
( Name, GridImage)
Select Name, GridImage
From #temp
I have a problem in fetching the image from database & it to Grid.
Error is
parameter is not valid. at system.drawing.image.fromstream
I think that my save method is wrong please help
Your method imageToByteArray() can return bytes with any value from 0 to 255. It's likely that your database does not support strings with such entirely arbitrary character values. Suggest that you instead convert the image bytes to base 64:
public static string ToBase64String(this System.Drawing.Image imageIn)
{
if (imageIn == null)
return null;
ImageConverter converter = new ImageConverter();
return Convert.ToBase64String((byte[])converter.ConvertTo(imageIn, typeof(byte[])));
}
public static Image FromBase64String(string imageString)
{
if (string.IsNullOrEmpty(imageString))
return null;
ImageConverter converter = new ImageConverter();
return (Image)converter.ConvertFrom(Convert.FromBase64String(imageString));
}
I used ImageConverter because it saves the image in its current format. If you want to save the image to a specific format -- System.Drawing.Imaging.ImageFormat.Gif in your case -- your code is correct.
Update
It looks as though you are making a more fundamental error. When you do
var s = "<GridImage><cdata>" + ((byte[])dgvDemo.CurrentRow.Cells[3].Value) + "</cdata></GridImage>";
You are basically doing
byte[] byteArray = (byte[])dgvDemo.CurrentRow.Cells[3].Value;
var s = "<GridImage><cdata>" + byteArray + "</cdata></GridImage>";
To perform this addition, .Net converts byteArray to a string by calling its ToString() method -- but this method has not been overridden in arrays and simply returns the type name. Thus you get "<GridImage><cdata>System.Byte[]</cdata></GridImage>", which is surely not what you want. You need to convert the byte array to a string explicitly, which Convert.ToBase64String() and Convert.FromBase64String() do for you.

FastReport export to image in multipage reports

I want to export a multi page report (FastReport) to image
var stream = new MemoryStream();
rpt.Export(new ImageExport(), result);
reports with one page is OK, but multipage reports have this error :
empty path name is not legal
Have any idea to solve this?!
You should use path, instead of stream.
Example with path:
using (FastReport.Report report = new FastReport.Report())
{
report.Load(#"C:\test.frx");
report.Prepare();
report.Export(new FastReport.Export.Image.ImageExport(), "myReport.png");
}
When report has more than one page, the following files will be created:
myReport.png
myReport.2.png
myReport.3.png
...
Here is solution with stream. You should set PageRange = PageRange.Current and set CurPage to appropriate value:
int count = 1;
using (FastReport.Report report = new FastReport.Report())
{
report.Load(#"C:\test.frx");
report.Prepare();
foreach (PageBase item in report.Pages)
{
string fileName = string.Format("myReport_{0}.png", count);
report.Export(new FastReport.Export.Image.ImageExport() { PageRange = PageRange.Current, CurPage = count }, fileName);
count++;
}
}

write and read from byte stream

I have a page where the User can either upload their own csv or enter values into a listbox which then creates a csv (in the background). Regardless of which way the csv gets created I need to upload that csv to our server via a byte stream.
My problem is that when Im creating the csv I shouldn't have to create a temporary file, I should be able to write to the stream then read it back for uploading. How can I remove the need for the temporary file?
current code which works (but uses temp file):
try {
string filename = DateTime.Now.ToString("MMddyyHmssf");
filename = filename + ".csv";
string directory = ConfigurationManager.AppSettings["TempDirectory"].ToString();
path = Path.Combine(directory, filename);
using (StreamWriter sw = File.CreateText(path)) {
foreach (ListItem item in this.lstAddEmailAddress.Items) {
sw.WriteLine(" , ," + item.ToString());
}
}
} catch (Exception ex) {
string error = "Cannot create temp csv file used for importing users by email address. Filepath: " + path + ". FileException: " + ex.ToString();
this.writeToLogs(error, 1338);
}
}
// put here for testing the byte array being sent vs ready byte[] byteArray = System.IO.File.ReadAllBytes(path);
myCsvFileStream = File.OpenRead(path);
nFileLen = (int)myCsvFileStream.Length;
I have tried
Stream myCsvFileStream;
using (StreamWriter sw = new StreamWriter(myCsvFileStream)) {
foreach (ListItem item in this.lstAddEmailAddress.Items) {
sw.WriteLine(" , ," + item.ToString());
}
}
However since myCsvFileStream is not initialized (because stream is a static class) it is always null.
Here is what I do with the data (byte stream) after creating the csv.
byte[] file = new byte[nFileLen];
myCsvFileStream.Read(file, 0, nFileLen);
bool response = this.repositoryService.SaveUsers(this.SelectedAccount.Id, file, this.authenticatedUser.SessionToken.SessionId);
myCsvFileStream.Close();
In the end I used StringBuilder to create my csv file contents. Then got a byte array of its contents and used that to populate my shared stream (I say shared because when the user enters their own CSV file it is a HttpPostedFile but when sending it to our server via the rest call (respositoryservices.saveusers) it uses the same byte stream that it would via this method)
StringBuilder csvFileString = new StringBuilder();
sharedStreamForBatchImport = new MemoryStream();
foreach (ListItem item in this.lstAddEmailAddress.Items) {
csvFileString.Append(",," + item.ToString() + "\\r\\n");
}
//get byte array of the string
byteArrayToBeSent = Encoding.ASCII.GetBytes(csvFileString.ToString());
//set length for read
byteArraySize = (int)csvFileString.Length;
//read bytes into the sharedStreamForBatchImport (byte array)
sharedStreamForBatchImport.Read(byteArrayToBeSent, 0, byteArraySize);
You want to create a new MemoryStream()
Here is a function I use to write CSV files
public static bool WriteCsvFile(string path, StringBuilder stringToWrite)
{
try
{
using (StreamWriter sw = new StreamWriter(path, false)) //false in ordre to overwrite the file if it already exists
{
sw.Write(stringToWrite);
return true;
}
}
catch (Exception)
{
return false;
}
}
stringToWrite is just a string that has been created that way :
public static bool WriteCsvFile(string path, DataTable myData)
{
if (myData == null)
return false;
//Information about the table we read
int nbRows = myData.Rows.Count;
int nbCol = myData.Columns.Count;
StringBuilder stringToWrite = new StringBuilder();
//We get the headers of the table
stringToWrite.Append(myData.Columns[0].ToString());
for (int i = 1; i < nbCol; ++i)
{
stringToWrite.Append(",");
stringToWrite.Append(myData.Columns[i].ToString());
}
stringToWrite.AppendLine();
//We read the rest of the table
for (int i = 0; i < nbRows; ++i)
{
stringToWrite.Append(myData.Rows[i][0].ToString());
for (int j = 1; j < nbCol; ++j)
{
stringToWrite.Append(",");
stringToWrite.Append(myData.Rows[i][j].ToString());
}
stringToWrite.AppendLine();
}
return WriteCsvFile(path, stringToWrite);
}

Categories