C# code to add hyper link in excel sheet - c#

Hi I am having an excel file containing multiple sheets.
One of the sheets will contain the hyperlink for other sheets.
While using the following code I have successfully added the link but
when I click on the link it gives error **"Refrence not valid"**
Code snippet:
private void AddHyperLink(Workbook xlWorkBook,int nfaultCount)
{
Excel.Worksheet xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
DateTime now = DateTime.Now;
xlWorkSheet.Name = "Summary"; //name of the sheet containing hyperlink
xlWorkSheet.Select(Type.Missing); //code to select the summary sheet
for (int i = 1; i <= nfaultCount; i++)
{
int x = i + 9;
string str = "Fault Code "+i + " of " + nfaultCount;
string strRange1 = "A" + x;
string strRange2 = "A" + x;
string strRange = strRange1 + ":" + strRange2; //location of the link
var Range = xlWorkSheet.get_Range(strRange);
// strRange1 = "!" + strRange1;
string strp="#" + i + " of " +nfaultCount + strRange1;
i +" of " nfaultCount==> name of the target worksheet
Range.Cells.Hyperlinks.Add(Range,strp, Type.Missing, "Fault Code Link", str);
}
xlWorkSheet.Columns["A:B"].AutoFit();
}
I have used the following link for my refrence
http://www.experts-exchange.com/Programming/Languages/.NET/Q_27912390.html
but its giving error Refrence is not valid.

The error message says your hyperlink address is invalid.
Try generating it as:
string strp="#'" + i + " of " +nfaultCount + "'!" + strRange1;
// Sample result: "#'4 of 5'!A3
instead of
string strp="#" + i + " of " +nfaultCount + strRange1;
// Sample result: #4 of 5A3
The above assumes the target worksheet name is "4 of 5".
Note that you need a ! character between the worksheet name and the range name.
You also need to enclose the worksheet name in single quotes if it contains one or more spaces.

Related

Transferring a tab separated variable file via clipboard to Excel but retaining line breaks WITHIN the cell

I am using C# Script in Tabular Editor to read a Power BI file and use clipboard to get information to Excel. Totally newbie to both so my code isn't great but works. My code is below.
For the Expression field I am using .Replace("\n"," ") to replace the line breaks with a blank space.
Otherwise the line broken text moves into the next row in Excel and doesn't align with the corresponding column anymore.
Is there a way I can achieve both
i.e. replace the line breaks with something in Excel that is recognized as a multiple line but still remains with in an Excel Cell.
I have googled and read multiple threads and tried \r, \x0A, CHAR(10), WrapText in Excel etc.
var tsv = "Table_Name\tTable_MeasureCount\tMeasure_Name\tMeasure_Description\tMeasure_DisplayFolder\tMeasure_IsHidden\tMeasure_DataType\tMeasure_FormatString\tMeasure_DataCategory\tMeasure_ErrorMessage\tMeasure_Expression";
foreach(var Table in Model.Tables)
foreach(var Measure in Table.Measures)
{
tsv += "\r\n" + Table.Name
+ "\t" + Table.Measures.Count
+ "\t" + Measure.Name
+ "\t" + Measure.Description
+ "\t" + Measure.DisplayFolder
+ "\t" + Measure.IsHidden
+ "\t" + Measure.DataType
+ "\t" + Measure.FormatString
+ "\t" + Measure.DataCategory
+ "\t" + Measure.ErrorMessage.Replace("\n"," ")
+ "\t" + Measure.Expression.Replace("\n"," ");
}
tsv.Output();
This is the logic I ended up with (I couldn't get a function to work in Tabular Editor)
var csv = "\"Table_Name\",\"Table_MeasureCount\",\"Measure_Name\",\"Measure_Description\",\"Measure_DisplayFolder\",\"Measure_IsHidden\",\"Measure_DataType\",\"Measure_FormatString\",\"Measure_DataCategory\",\"Measure_ErrorMessage\",\"Measure_Expression\"";
string str1 = "\r\n\"";
string str2 = "\",\"";
string str3 = "\"";
//foreach(var Measure in Model.AllMeasures)
foreach(var Table in Model.Tables)
{
foreach(var Measure in Table.Measures)
{
csv += str1 + Table.Name
+ str2 + Table.Measures.Count
+ str2 + Measure.Name
+ str2 + Measure.Description
+ str2 + Measure.DisplayFolder
+ str2 + Measure.IsHidden
+ str2 + Measure.DataType
+ str2 + Measure.FormatString.Replace("\"","\"\"")
+ str2 + Measure.DataCategory
+ str2 + Measure.ErrorMessage.Replace("\"","\"\"")
+ str2 + Measure.Expression.Replace("\"","\"\"")
+ str3;
}
}
csv.Output();
Now we have established CSV is the best option as it allows for line-breaks, I'd suggest the following:
First create a simple function to parse a string into a safe format:
public string stringToCsvSafe(string str)
{
return "\"" + str.Replace("\"", "\"\"") + "\"";
}
Then in your loop build your output string, something like this:
var newRow = new List<object>() {
Table.Name,
Table.Measures.Count,
stringToCsvSafe(Measure.Name),
stringToCsvSafe(Measure.Description),
...
};
csv += string.Join(",", newRow) + "\n";

Reading From Excel File - Cells with Values Show Null

I have written some code that reads every row in an excel file (for two specific columns) which I will be using later to execute an update SQL Query for each of the rows with a value.
I have displayed these values in a listbox, and I am getting far more nulls than expected when comparing with the stock codes in the excel file.
I have tried changing the formatting of the excel file, but this did not make any difference. There are rows where there definitely are stock codes at that position, but when the program does the cell comparison the program identifies them as nulls when they actually have values.
Does anyone know what the problem is with my code?
private void btnStockCodes_Click(object sender, RoutedEventArgs e)
{
string file = #"\\amn-fs-01\users$\Shanel\Desktop\Stock Codes.xlsx";
Microsoft.Office.Interop.Excel.Application ExcelApp = new Microsoft.Office.Interop.Excel.Application();
Workbook ExcelWorkbook = ExcelApp.Workbooks.Open(file);
Worksheet ews = ExcelApp.ActiveWorkbook.Sheets[1];
Microsoft.Office.Interop.Excel.Range usedRange = ews.UsedRange;
int TotalCounter = 0;
string StockCode = "";
string ReserveID = "";
int nullcounter = 0;
int foundcounter = 0;
foreach (Microsoft.Office.Interop.Excel.Range row in usedRange.Rows)
{
StockCode = "";
ReserveID = "";
TotalCounter = TotalCounter + 1;
if (row.Cells[TotalCounter,7].Value == null)
{
Listbox1.Items.Add(TotalCounter + " null");
nullcounter = nullcounter + 1;
}
else
{
StockCode = row.Cells[TotalCounter,7].Value.ToString();
ReserveID = row.Cells[TotalCounter, 3].Value.ToString();
Listbox1.Items.Add(TotalCounter + " " + StockCode + " " + ReserveID);
foundcounter = foundcounter + 1;
}
}
txtTotal1.Text = foundcounter.ToString() + " Found";
txtTotal2.Text = nullcounter.ToString() + " Null Values";
txtTotal3.Text = TotalCounter.ToString() + " Total Records";
}
I would not trust that Worksheet.UsedRange always works correctly, sometimes it contains more cells than it should, or less. My suggestion is to read all rows in worksheet, while you have any values. Once there are no more values, just stop reading it.
And if you have too many rows, you can read all values at the same time into an array, like here and work with the array.
Thanks for your contributions, I have resolved the error!
It occurs in the row.Cells[TotalCounter,7].Value.ToString()
It should have been row.Cells[7].Value.ToString()
There was no need for me to specify a row index as that's taken care of in the Foreach loop. I will look into alternative ways of writing the code as Worksheet.UsedRange might not work in all cases as Alex suggested.

c# Windows Form, replace string in textbox (file content) with another string

I have a textbox that contains all of the lines of a loaded file.
It looks like this:
I am able to load a specific line of the file that contains a specific string using this in the app:
How would I be able to update the file/main textbox after I press the "Edit Module" button, if any of the textboxes would be changed .
For example, I would change Exam Weighting: "0.4" to Exam Weighting: "0.6", then press the "Edit Module" button which would edit the main textbox(file content). Which then would allow me to save the file with the updated content.
This is the code I am using to get a specific line from the file based on string from a textbox:
private void editModuleButton_Click(object sender, EventArgs e)
{
citation = editModuleComboBox.Text;
citationChange();
}
private void citationChange()
{
List<string> matchedList = new List<string>();
string[] linesArr = File.ReadAllLines(fileName);
//find matches
foreach (string s in linesArr)
{
if (s.Contains(citation))
{
matchedList.Add(s); //matched
}
}
//output
foreach (string s in matchedList)
{
string citationLine = s;
string[] lineData = citationLine.Split(',');
selectedModuleLabel.Text = lineData[2];
moduleTitleTextBox.Text = lineData[3];
creditsTextBox.Text = lineData[4];
semesterTextBox.Text = lineData[5];
examWeightingTextBox.Text = lineData[6];
examMarkTextBox.Text = lineData[7];
testWeightingTextBox.Text = lineData[8];
testMarkTextBox.Text = lineData[9];
courseworkWeightingTextBox.Text = lineData[10];
courseworkMarkTexbox.Text = lineData[11];
}
}
If somebody with enough rep could insert the images to this post, that would be great. Thanks
This solution might not be the perfect, but should work for you. What you need to do is whenever the Edit Module button is pressed, create a new string based on the text fields and replace it with the original line. First declare a string variable private string ChangedString = ""; inside the class, then:
foreach (string s in matchedList)
{
string citationLine = s;
string[] lineData = citationLine.Split(',');
string Stream = lineData[0]; //Store this somewhere so that it can be accessed later
string Stage = lineData[1]; //Store this somewhere so that it can be accessed later
selectedModuleLabel.Text = lineData[2];
moduleTitleTextBox.Text = lineData[3];
creditsTextBox.Text = lineData[4];
semesterTextBox.Text = lineData[5];
examWeightingTextBox.Text = lineData[6];
examMarkTextBox.Text = lineData[7];
testWeightingTextBox.Text = lineData[8];
testMarkTextBox.Text = lineData[9];
courseworkWeightingTextBox.Text = lineData[10];
courseworkMarkTexbox.Text = lineData[11];
}
store Stream and Stage in any Textbox/ComboBox if you already haven't then replace them accordingly in the following line. Now in EditButton_Click [Click Event] write:
ChangedString = Stream + "," + Stage + "," + selectedModuleLabel.Text + "," + moduleTitleTextBox.Text
+ "," + creditsTextBox.Text + "," + semesterTextBox.Text + "," + examWeightingTextBox.Text + ","
+ examMarkTextBox.Text + "," + courseworkWeightingTextBox.Text + "," + courseworkMarkTexbox.Text;
Now replace this string with the original line.
Edit: As you would get the line number which is being edited, store it in a variable, let's say
int LineBeingEdited = 3 //Supposing line number three is being edited.
Then again in the same Click event you can write this:
ChangedString = Stream + "," + Stage + "," + selectedModuleLabel.Text + "," + moduleTitleTextBox.Text
+ "," + creditsTextBox.Text + "," + semesterTextBox.Text + "," + examWeightingTextBox.Text + ","
+ examMarkTextBox.Text + "," + courseworkWeightingTextBox.Text + "," + courseworkMarkTexbox.Text;
var lines = TextBox1.Lines;
lines[LineBeingEdited] = ChangedString;
TextBox1.Lines = lines;
EDIT 2: To get the line number I would suggest you to modify your for each loop to for loop. Also add a int variable to store the line number inside the class like : private int LineBeingEdited = 0;
Modify this for each :
foreach (string s in linesArr)
{
if (s.Contains(citation))
{
matchedList.Add(s); //matched
}
}
To for loop:
for (int a = 0; a < linesArr.Length; a++)
{
if (s.Contains(citation))
{
matchedList.Add(linesArr[a]); //matched
LineBeingEdited = a;
break; //breaks the loop when a match is found
}
}
The above method is being used, taking into consideration that there will always be a single match. LineBeingEdited will now have the line number and can be accessed from anywhere in the class

C# generated worksheet is read-only and locked

I have a problem with opening and saving Excel file which my C# program generated. Every time I made some changes manually and try to save the Excel file, the popup message ask me to save a copy of this file because it is read-only. It is ok but annoying. My excel file is produced by my C# program. Here is my code snippet:
/**
* Save the matched data
* */
public void saveMatch(List<String> saveB, List<String> saveG, Excel.Worksheet bellSheet, Excel.Worksheet GSMSheet, String fileurl, String mCode, String prioName,int sNumber = 0)
{
object misValue = System.Reflection.Missing.Value;
Excel.Application newApp = new Excel.Application();
Excel.Workbook newWB = newApp.Workbooks.Add(misValue);
Excel.Worksheet newWS = newWB.Worksheets.get_Item(1);
String colName1 = bSheet.get_Range("A1").Cells.Value;
String colName2 = GSheet.get_Range("A1").Cells.Value;
int i = 2;//start copy from row two of the Sheet, row one is the column name
newWS.Cells[1, 2] = colName2;//copy the column name
newWS.Cells[1, 1] = colName1;//copy the column name
//Copy excatly matching data
for (int j = 0; j < saveB.Count; j++)
{
newWS.Cells[i, 1] = saveB[j];
newWS.Cells[i, 2] = saveG[j];
//Console.WriteLine(saveG[j] + " : " + saveB[j]);
i++;
}
if (sNumber==0)
{
if (prioName.Equals("None"))
{
newWB.SaveAs(fileurl + #"\MdResults_" +"None_"+ mCode + ".xlsx");
}
else
{
newWB.SaveAs(fileurl + #"\MdResults_" + prioName+"_"+mCode + ".xlsx");
}
}
else
{
if (prioName.Equals("None"))
{
newWB.SaveAs(fileurl + #"\MdResults_" + "None_"+mCode + "_" + sNumber + ".xlsx");
}
else
{
newWB.SaveAs(fileurl + #"\MdResults_" +prioName + "_"+mCode + "_" +sNumber + ".xlsx");
}
}
newWB.Close(0);
newApp.Quit();
}
Program runs ok and I can open the saved Excel file successfully. I just wondering am I missing something in the C# code or I just need to modify something in Excel file itself? I want the excel file which my program generated can be modified and saved as normal without a popup message to ask me to save as a copy. Thanks for the help.
If you don't close newApp, an Excel process will stick around in memory and keep your file locked.
Check your task list to confirm this is happening.
Try adding the following after saving your file
newApp.Close(0);
newApp.Quit();

How to import into a template excel file (C#)

I have the code below to save data into a excel file(.csv).
private void SavedataToolStripMenuItem_Click(object sender, EventArgs e)
{
now_status.Text = "save data to excel";
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{[![enter image description here][1]][1]
selectedFileName = saveFileDialog1.FileName + ".csv";
System.Text.Encoding enc = System.Text.Encoding.GetEncoding("Shift_JIS");
System.IO.StreamWriter sr = new System.IO.StreamWriter(selectedFileName, false, enc);
int rowCountA = int.Parse(objA_n.Text);
int rowCountB = int.Parse(objB_n.Text);
string field;
field = "Saved Data" + "\r\n" + "Numb,Time(S),AX,AY,BX,BY" + "\r\n";
sr.Write(field);
for (int i = 1; i < rowCountA + 1; i++)
{
string fieldA;
fieldA = "A" + dn_objA[i].ToString() + "," + dtime_objA[i].ToString() + "," + dx_objA[i].ToString() + "," + dy_objA[i].ToString() + ",," + "\r\n";
sr.Write(fieldA);
}
for (int i = 1; i < rowCountB + 1; i++)
{
string fieldB;
fieldB = "B" + dn_objB[i].ToString() + "," + dtime_objB[i].ToString() + ",,," + dx_objB[i].ToString() + "," + dy_objB[i].ToString() + "\r\n";
sr.Write(fieldB);
}
sr.Close();
sr.Close();
}
}
This Generates a simple excel file like this below. Object values will be inserted below the second row.
Is there a way to do the same thing, but into a template excel file? I have an excel file like the one below.
I would like the imported data to show on the left hand side of the excel file.
Also, I want to use macros that I made in the second excel file shown.

Categories