DataGridView Printing - c#

How do I print specified rows out to a file from a DataGridView?
Also how can I print out certain columns?
This is what I have been trying to work with.. but it is not working..:
private void saveButton_Click(object sender, EventArgs e)
{
saveFile1.DefaultExt = "*.txt";
saveFile1.Filter = ".txt Files|*.txt|All Files (*.*)|*.*";
saveFile1.RestoreDirectory = true;
if (saveFile1.ShowDialog() == DialogResult.OK)
{
StreamWriter sw = new StreamWriter(saveFile1.FileName);
List<string> theList = new List<string>();
foreach (var line in theFinalDGV.Rows)
{
if (line.ToString().Contains("FUJI"))
richTextBox1.AppendText(line + "\n");
}
}
}
Can anyone help me in the right direction?

DataGridViewRow.ToString() only gives you the typename back, not the row content. You can use this extender to get the rowcontent ('ColumnName'):
public static class Extender {
public static string RowToString(this DataGridViewRow dgvr) {
string output = "";
DataGridView dgv = dgvr.DataGridView;
foreach (DataGridViewCell cell in dgvr.Cells) {
DataGridViewColumn col = cell.OwningColumn;
output += col.HeaderText + ":" + cell.Value.ToString() + ((dgv.Columns.IndexOf(col) < dgv.Columns.Count - 1) ? ", " : "");
}
return output;
}
}
if you only want the content of the row without the coulmn-headername use this (space separated):
public static class Extender {
public static string RowToString(this DataGridViewRow dgvr) {
string output = "";
foreach (DataGridViewCell cell in dgvr.Cells) {
output += cell.Value.ToString() + " ";
}
return output.TrimEnd();
}
}
your code will look like this:
class YourClass
{
private void saveButton_Click(object sender, EventArgs e)
{
saveFile1.DefaultExt = "*.txt";
saveFile1.Filter = ".txt Files|*.txt|All Files (*.*)|*.*";
saveFile1.RestoreDirectory = true;
if (saveFile1.ShowDialog() == DialogResult.OK)
{
StreamWriter sw = new StreamWriter(saveFile1.FileName);
List<string> theList = new List<string>();
foreach (var line in theFinalDGV.Rows)
{
string linecontent = line.RowToString();
if (linecontent.Contains("FUJI"))
richTextBox1.AppendText(linecontent + "\n");
}
}
}
}
public static class Extender {
public static string RowToString(this DataGridViewRow dgvr) {
string output = "";
DataGridView dgv = dgvr.DataGridView;
foreach (DataGridViewCell cell in dgvr.Cells) {
DataGridViewColumn col = cell.OwningColumn;
output += col.HeaderText + ":" + cell.Value.ToString() + ((dgv.Columns.IndexOf(col) < dgv.Columns.Count - 1) ? ", " : "");
}
return output;
}
}

Related

WinForms DataGridView does not respond while listing images

I have an application that allows the users to upload the selected images to the DataGridView and perform operations on their. However, when multiple images are selected, the Form freezes until the image information is uploaded to the DataGridView. I have tried BackgroundWorker for this, but it didn't work either. My codes look like this:
private void button1_Click(object sender, EventArgs e)
{
var file = new OpenFileDialog
{
Filter = #"TIFF |*.tiff| TIF|*.tif",
FilterIndex = 1,
Title = #"Select TIFF file(s)...",
Multiselect = true
};
if (file.ShowDialog() == DialogResult.OK)
{
Listing(file.FileNames);
}
}
private void Listing(string[] files)
{
foreach (var file in files)
{
var pic_name = Path.GetFileName(file);
if (file != null)
{
// Image from file
var img = Image.FromFile(file);
// Get sizes of TIFF image
var pic_sizes = img.Width + " x " + img.Height;
// Get size of TIFF image
var pic_size = new FileInfo(file).Length;
//Create the new row first and get the index of the new row
var rowIndex = dataGridView1.Rows.Add();
//Obtain a reference to the newly created DataGridViewRow
var row = dataGridView1.Rows[rowIndex];
//Now this won't fail since the row and columns exist
row.Cells["name"].Value = pic_name;
row.Cells["sizes"].Value = pic_sizes + " pixels";
row.Cells["size"].Value = pic_size + " bytes";
}
}
}
How can I solve this problem?
EDIT: After Alex's comment, I tried like this:
private void button1_Click(object sender, EventArgs e)
{
var file = new OpenFileDialog
{
Filter = #"TIFF |*.tiff| TIF|*.tif",
FilterIndex = 1,
Title = #"Select TIFF file(s)...",
Multiselect = true
};
if (file.ShowDialog() == DialogResult.OK)
{
_ = Test(file.FileNames);
}
}
private async Task Test(string[] s)
{
await Task.Run(() => Listing(s));
}
private void Listing(string[] files)
{
BeginInvoke((MethodInvoker) delegate
{
foreach (var file in files)
{
var pic_name = Path.GetFileName(file);
if (file != null)
{
// Image from file
var img = Image.FromFile(file);
// Get sizes of TIFF image
var pic_sizes = img.Width + " x " + img.Height;
// Get size of TIFF image
var pic_size = new FileInfo(file).Length;
//Create the new row first and get the index of the new row
var rowIndex = dataGridView1.Rows.Add();
//Obtain a reference to the newly created DataGridViewRow
var row = dataGridView1.Rows[rowIndex];
//Now this won't fail since the row and columns exist
row.Cells["name"].Value = pic_name;
row.Cells["sizes"].Value = pic_sizes + " pixels";
row.Cells["size"].Value = pic_size + " bytes";
}
}
});
}
But unfortunately the result is same.
I think the whole problem is in collecting image datas. Because a ready list will not take longer to load if it will not need extra processing. For this reason, I prepared a scenario like below.
private readonly BindingList<Tiff> _tiffs = new BindingList<Tiff>();
private void button1_Click(object sender, EventArgs e)
{
Listing();
}
private void Listing()
{
foreach (var f in _tiffs)
{
if (f != null)
{
var rowIndex = dataGridView1.Rows.Add();
//Obtain a reference to the newly created DataGridViewRow
var row = dataGridView1.Rows[rowIndex];
//Now this won't fail since the row and columns exist
row.Cells["ColName"].Value = f.ColName;
row.Cells["ColSizes"].Value = f.ColSizes + " pixels";
row.Cells["ColSize"].Value = f.ColSize + " bytes";
}
}
}
public static List<string> Files(string dir, string ext = "*.tiff")
{
var DirInfo = new DirectoryInfo(dir);
return DirInfo.EnumerateFiles(ext, SearchOption.TopDirectoryOnly).Select(x => x.FullName).ToList();
}
public void SetSource()
{
// Source folder of images...
var files = Files(#"___SOURCE_DIR___");
var total = files.Count;
var i = 1;
foreach (var file in files)
{
var pic_name = Path.GetFileName(file);
var img = Image.FromFile(file);
// Get sizes of TIFF image
var pic_sizes = img.Width + " x " + img.Height;
// Get size of TIFF image
var pic_size = new FileInfo(file).Length.ToString();
_tiffs.Add(new Tiff(pic_name, pic_sizes, pic_size));
BeginInvoke((MethodInvoker)delegate
{
label1.Text = $#"{i} of {total} is added to the BindingList.";
});
i++;
}
}
private void button2_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
SetSource();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// Set something if you want.
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Set something if you want.
}
public class Tiff
{
public Tiff(string name, string sizes, string size)
{
ColName = name;
ColSizes = sizes;
ColSize = size;
}
public string ColName { get; set; }
public string ColSizes { get; set; }
public string ColSize { get; set; }
}
And here is the result:

When searching for text in files how can i repeat the search without retrieving the files all over again?

I'm doing two methods when searching. First retrieving files and then searching in the files.
But in some cases i change only the searching text i search for and i want to repeat the searching in the same directories and files. So how can i make that it will remember the last retrieved files ?
This is the button click event to start the backgorundworker and the searching methods:
private void startButton_Click(object sender, EventArgs e)
{
ListViewCostumControl.lvnf.Items.Clear();
numberoffiles = 0;
numberofrestrictedFiles = 0;
numberofdirs = 0;
label24.Text = "0";
label1.Text = "0";
label15.Text = "0";
Logger.Write("Operation started");
label21.Text = "Phase 1: Retrieving files";
label21.Visible = true;
startButton.Enabled = false;
stopButton.Enabled = true;
pauseresumeButton.Enabled = true;
label1.Select();
timer1.Start();
if (!backgroundWorker1.IsBusy)
{
SetWorkerMode(true);
backgroundWorker1.RunWorkerAsync();
}
}
This is the backgroundworker events in the completed i'm writing to a text file some information but not the whole retrieved files.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
_stopwatch.Restart();
string[] values = textBox1.Text.Split(new string[] { ",," }, StringSplitOptions.None);
DirSearch(textBox3.Text, textBox2.Text, values, worker, e);
_stopwatch.Stop();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
MyProgress mypro = (MyProgress)e.UserState;
ListViewCostumControl.lvnf.Items.Add(mypro.Report1);
label15.Text = mypro.Report2;
label15.Visible = true;
if (ListViewCostumControl.lvnf.Items.Count > 9)
textBox4.Enabled = true;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == true)
{
label1.Select();
_stopwatch.Stop();
label24.Text = "0";
label5.Text = "00:00:00";
label1.Text = "0";
label11.Text = "0";
label15.Text = "0";
label24.Text = "0";
pauseresumeButton.Enabled = false;
stopButton.Enabled = false;
startButton.Enabled = true;
timer1.Stop();
ListViewCostumControl.lvnf.Items.Clear();
Logger.Write("Operation cancelled");
button4.Enabled = true;
}
if (e.Error != null)
{
}
else
{
label1.Select();
_stopwatch.Stop();
timer1.Stop();
stopButton.Enabled = false;
pauseresumeButton.Enabled = false;
startButton.Enabled = true;
label21.Text = "Last operation ended at: " + DateTime.Now;
Logger.Write("Number of retrieved files: " + numberoffiles);
Logger.Write("Number of restricted files: " + numberofrestrictedFiles);
Logger.Write("Number of searched files: " + numberofdirs);
Logger.Write("Number of results: " + label15.Text);
Logger.Write("Searched root directory: " + textBox3.Text);
Logger.Write("Operation time: " + _stopwatch.Elapsed);
Logger.Write("Operation ended");
Logger.Write(" ");
button4.Enabled = true;
mCompleted = true;
if (mClosePending) this.Close();
}
}
This is the searching methods:
int numberofdirs = 0;
void DirSearch(string rootDirectory, string filesExtension, string[] textToSearch, BackgroundWorker worker, DoWorkEventArgs e)
{
List<string> resultsoftextfound = new List<string>();
List<string> resultsoftextfound1 = new List<string>();
List<string> filePathList = new List<string>();
int numberoffiles = 0;
try
{
filePathList = SearchAccessibleFilesNoDistinct(rootDirectory, null,worker,e).ToList();
}
catch (Exception err)
{
string ad = err.ToString();
}
label21.Invoke((MethodInvoker)delegate
{
label21.Text = "Phase 2: Searching in files";
});
MyProgress myp = new MyProgress();
myp.Report4 = filePathList.Count.ToString();
foreach (string file in filePathList)
{
try
{
_busy.WaitOne();
if (worker.CancellationPending == true)
{
e.Cancel = true;
return;
}
bool reportedFile = false;
for (int i = 0; i < textToSearch.Length; i++)
{
if (File.ReadAllText(file).IndexOf(textToSearch[i], StringComparison.InvariantCultureIgnoreCase) >= 0)
{
resultsoftextfound.Add(file + " " + textToSearch[i]);
if (!reportedFile)
{
numberoffiles++;
myp.Report1 = file;
myp.Report2 = numberoffiles.ToString();
myp.Report3 = textToSearch[i];
backgroundWorker1.ReportProgress(0, myp);
reportedFile = true;
}
}
}
numberofdirs++;
label1.Invoke((MethodInvoker)delegate
{
label1.Text = string.Format("{0}/{1}", numberofdirs, myp.Report4);
label1.Visible = true;
});
}
catch (Exception)
{
}
}
}
And SearchAccessibleFilesNoDistinct method:
string restrictedFile = "";
List<string> restrictedFiles = new List<string>();
int numberofrestrictedFiles = 0;
int numberoffiles = 0;
IEnumerable<string> SearchAccessibleFilesNoDistinct(string root, List<string> files,BackgroundWorker worker, DoWorkEventArgs e)
{
_busy.WaitOne();
if (files == null)
files = new List<string>();
if (Directory.Exists(root))
{
foreach (var file in Directory.EnumerateFiles(root))
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
return files;
}
restrictedFile = file;
string ext = Path.GetExtension(file);
if (!files.Contains(file) && ext == textBox2.Text)
{
files.Add(file);
}
numberoffiles++;
label24.Invoke((MethodInvoker)delegate
{
label24.Text = numberoffiles.ToString();
label24.Visible = true;
});
}
foreach (var subDir in Directory.EnumerateDirectories(root))
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
return files;
}
try
{
SearchAccessibleFilesNoDistinct(subDir, files,worker, e);
}
catch (UnauthorizedAccessException)
{
restrictedFiles.Add(restrictedFile);
numberofrestrictedFiles++;
label11.Invoke((MethodInvoker)delegate
{
label11.Text = numberofrestrictedFiles.ToString();
label11.Visible = true;
});
continue;
}
}
}
return files;
}
The idea is to give the user and option to choose if to save or not somehow the last retrieved files so when he repeat the searching it will not retrieve the whole files over again only will search in them. In other words if i repeat the last searching just make the second method.
I call it Phase 1 and Phase 2.
The problem might be that if i save the last retrieved files to a text files or something like that it might be a large file on the hard disk ?
Another problem is when i type the text to search for in textBox1 if i type two words with a space it's not the same without a space for example: Form1 is not the same as Form 1 How can i make that it will search for both results Form1 and Form 1 ?
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (textBox1.Text != "" && textBox3.Text != "" && Directory.Exists(textBox3.Text))
{
startButton.Enabled = true;
Properties.Settings.Default["Setting2"] = textBox1.Text;
Properties.Settings.Default.Save();
}
else
{
startButton.Enabled = false;
}
}
I did that if the user type in the textBox1 ,,
It will consider the text after it as another search text.
void lvnf_SelectedIndexChanged(object sender, EventArgs e)
{
if (ListViewCostumControl.lvnf.SelectedItems.Count > 0)
{
results = new List<int>();
richTextBox1.Text = File.ReadAllText(ListViewCostumControl.lvnf.Items[ListViewCostumControl.lvnf.SelectedIndices[0]].Text);
FileInfo fi = new FileInfo(ListViewCostumControl.lvnf.Items[ListViewCostumControl.lvnf.SelectedIndices[0]].Text);
label17.Text = ExtensionMethods.ToFileSize(fi.Length);
label17.Visible = true;
filePath = Path.GetDirectoryName(fi.FullName);
string word = textBox1.Text;
string[] test = word.Split(new string[] { ",," }, StringSplitOptions.None);
foreach (string myword in test)
{
HighlightPhrase(richTextBox1, myword, Color.Yellow);
label16.Text = results.Count.ToString();
label16.Visible = true;
if (results.Count > 0)
{
numericUpDown1.Maximum = results.Count;
numericUpDown1.Enabled = true;
richTextBox1.SelectionStart = results[(int)numericUpDown1.Value - 1];
richTextBox1.ScrollToCaret();
}
}
}
}
For example if i type to search for Form1,,Form 1
Then it will search for all the results of Form1 and of Form 1
Or if i type Form1,,Help
Then the results will be also for Form1 and for Help.
The question not sure if a problem is more logic. When i type only Form1 should i consider it somehow also as Form 1 or i should leave it as it is now Form1,,Form 1 ?
Before i searched for SwitchCameras and it found results but before that i searched for Switch Cameras and it didn't find any results and i didn't put ,, between the Switch Cameras.
So i think by logic Switch Cameras should also find SwitchCameras.
So how can i change this searching rule so if there is no ,, but there is a space between the words search also for one word ?
Switch Cameras will also find SwitchCameras but Switch,,Cameras might find more results.

Sending selected listview data to another forms textbox

Hello i have got one listview that has txt files names inside one folder in desktop. So as i right data there is delete update and add so when i select one item and right click i want that data name to fill name textbox when its opened so its like basicly if i pick 1.1.2 and select update delete for will open and fixx textbox1 as the selectd datas name
-i tried few things like public statci string but when i use it and run program listview shows empty like there is nothing inside
private void liste_Load(object sender, EventArgs e)
{
#region listview fonksiyonları
listView1.FullRowSelect = true;
listView1.View = View.Details;
listView1.Columns.Add("Versiyon No", 133, HorizontalAlignment.Left);
listView1.Columns.Add("Açıklama", 200, HorizontalAlignment.Left);
listView1.Columns.Add("Tarih", 154, HorizontalAlignment.Left);
#endregion
#region listviewde txt dosyalarını gösterme
string[] dosyalar = System.IO.Directory.GetFiles(masaustu + "\\Versiyonlar");
string k = "";
int deger = 0;
foreach (var item in dosyalar)
{
ListViewItem lili = new ListViewItem();
deger = item.LastIndexOf("\\");
k = item.Remove(0, deger);
k = k.Remove(0, 1);
lili.Text = k;
StreamReader oku = new StreamReader(masaustu + "\\" + "Versiyonlar" + "\\" + k);
string OkunanVeri = oku.ReadToEnd();
string[] dizi = OkunanVeri.Split(new string[] { ";", "$" }, StringSplitOptions.RemoveEmptyEntries);
lili.SubItems.Add(dizi[0]);
lili.SubItems.Add(dizi[1]);
listView1.Items.Add(lili);
}
}
#endregion
#region txt içindekileri textboxda göstermek
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
liste frm = new liste();
try
{
string a = "";
a = "";
a = listView1.SelectedItems[0].SubItems[0].Text;
StreamReader oku = new StreamReader(masaustu + "\\" + "Versiyonlar" + "\\" + a);
string OkunanVeri = oku.ReadToEnd();
string[] dizi = OkunanVeri.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
foreach (var item in dizi)
{
textBox1.Text = OkunanVeri;
}
oku.Close();
}
catch
{
}
}
this is the listview codes if its going to help you please help me i just started c#and i cant figure out how to do it
i dont know what u looking for , this may help
in list view form:
private void openMenuItem_Click(object sender, EventArgs e)//contentmenu openbtn
{
if (listView1.SelectedIndices.Count > 0)//in listview form//on_click opnbtn
{
string strSlctdtext=Convert.ToString(listView1.Items[listView1.SelectedIndices[0]].SubItems[1].Text);
TextBoxform objTextBoxform = new TextBoxform(strListSelectedtext);
if (objTextBoxform.ShowDialog() == DialogResult.OK)
{
//do somthing if u want some output from textboxform in return
}
}
}
in textbox form
public TextBoxform(string strListviewselected)
{
InitializeComponent();
textBox1.Text = strListviewselected;
}

How to use validation in DataGridView

In my program, when I click a particular row in DataGridView, if that row contains "\" it should pop up an error message that "\ is not allowed in name or in path". I don't know how to do that.
Here is the code:
namespace OVF_ImportExport
{
public partial class Form1 : Form
{
string sName = "";
string sPath = "";
public Form1()
{
InitializeComponent();
}
private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
sName = row.Cells[0].Value.ToString();
sPath = row.Cells[1].Value.ToString();
}
}
private void BtnCreate_Click(object sender, EventArgs e)
{
richTextBox1.Text = "";
StreamWriter file = new StreamWriter("Export.bat");
file.WriteLine("c: ");
file.WriteLine("cd \\");
file.WriteLine("cd Program Files ");
file.WriteLine("cd VMware");
file.WriteLine("cd VMware OVF Tool");
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
sName = row.Cells[0].Value.ToString();
sName = sName.Trim();
sPath = row.Cells[1].Value.ToString();
file.WriteLine("start ovftool.exe --powerOffSource vi://" + TxtUsername.Text + ":" + TxtPassword.Text + "#"
+ TxtIP.Text + sPath + " " + "\"" + TxtBrowsepath.Text + "\\" + sName + "\\" + sName + ".ovf" + "\"" + Environment.NewLine);
}
file.WriteLine("pause");
MessageBox.Show("Batch File Created","Batch File");
file.Close();
}
try using this:
// Attach DataGridView events to the corresponding event handlers.
this.dataGridView1.CellValidating += new DataGridViewCellValidatingEventHandler(dataGridView1_CellValidating);
method for above event handler:
private void dataGridView1_CellValidating(object sender,
DataGridViewCellValidatingEventArgs e)
{
// Validate the CompanyName entry by disallowing empty strings.
if (dataGridView1.Columns[e.ColumnIndex].Name == "CompanyName")
{
if (String.IsNullOrEmpty(e.FormattedValue.ToString()))
{
dataGridView1.Rows[e.RowIndex].ErrorText =
"Company Name must not be empty";
e.Cancel = true;
}
}
}

SaveFileDialog Menuclick Item Doesnt Work.

If I set path = "C:\\MSREAD.txt"; and Click on SaveAs Menu Item ,it saves Filetext,But If I dont give the String path and save it from saveFD.FileName it doesnt work.Please help me with this issue.
Thanks a lot
public void SaveToFile()
{
String SavedFile = "";
saveFD.InitialDirectory = #"C:";
saveFD.Title = "Save a Text File";
saveFD.FileName = "";
RichTextBox richTextBox1 = new RichTextBox();
saveFD.Filter = "Text Files|*.txt|All Files|*.*";
try
{
if (saveFD.ShowDialog() != DialogResult.Cancel)
{
SavedFile = saveFD.FileName;
path = SavedFile.ToString();
//path = "C:\\MSREAD.txt";
MessageBox.Show(path);
richTextBox1.SaveFile(path, RichTextBoxStreamType.PlainText);
SaveMyTextBoxContents(path);
}
}
catch(Exception e)
{
MessageBox.Show(e.ToString());
}
}
private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
{
SaveToFile();
}
public void SaveMyTextBoxContents(string path)
{
if (listBoxItems.SelectedIndex == -1)
{
if (rdBtnSlow.Checked && rdBtnNo.Checked)
{
using (StreamWriter outputFile = new StreamWriter(path))
{
foreach (string item in listBoxItems.Items)
{
saveAllText = slowNo + " " + item;
outputFile.WriteLine(saveAllText);
}
}
}
}
}
Here is your problem:
richTextBox1.SaveFile(path, RichTextBoxStreamType.PlainText);
SaveMyTextBoxContents(path);
You first save the richTextBox text to file, but then override the same file with SaveMyTextBoxContents, However the file is empty because of SaveMyTextBoxContents method will only save something if some conditions are true "not selected item and both check boxes are checked", and the listBoxItems.Items.Count > 0 which apparently not the case

Categories