Paste into Excel locked cells - excel

I'm creating a template for users to input data into. All I want them to be able to do is copy their data from their source and put it into Cells A21-D21. Once pasted they cannot delete or alter anything, excel is used only to be able to print. Repasting is fine as this will be a template. Ideally, users would export directly into this protected worksheet and be done with it, but instrument software just calls for excel not a specific database location.
In short, users get data from an instrument and it is saved in a format that it cannot be manipulated but neither can it be shown on any computer except what's connected to the instrument. I need this data to be put into excel but cannot be altered. Auditors can compare the Raw data to the excel if they choose.
Is there a way to have worksheet protected and select the one unlocked cell(Format Cell), A1, and then have the entire range of A21-D21 filled/pasted into?
The thinking is that people will manipulate the raw data to get the answers they want but this will limit users to paste only.
So I guess, simply, I'm hoping to find a way to allow users to copy/paste and THAT'S IT! ?

I don't know if there is a way to do what you want inside Excel, but it can be done programatically.
// Note: need to add reference to Microsoft.Office.Interop.Excel to get these namespaces
// In Visual Studio, choose Project > Add Reference > COM > Type Libraries >
// Microsoft Excel 16.0 Object Library
using Microsoft.Office.Interop.Excel;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string fileName = #"c:\users\eric.sundquist\desktop\book1.xlsx";
int worksheetNumber = 1;
List<string> contents = new List<string> { "1", "2", "3", "4" };
PasteIntoProtectedSheet(fileName, worksheetNumber, contents);
}
static void PasteIntoProtectedSheet(string fileName, int worksheetNumber,
List<string> contents)
{
Application excel = new Application();
Workbook workbook = excel.Workbooks.Open(fileName);
workbook.Sheets[worksheetNumber].Unprotect();
// Can pass in password as parameter if needed
Range range = workbook.Sheets[1].Range("A21:D21");
for (int column = 0; column < contents.Count; column++)
{
range.Cells[1, column + 1] = contents[column];
}
workbook.Sheets[worksheetNumber].Protect();
workbook.Save();
workbook.Close();
Marshal.ReleaseComObject(range);
Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(excel);
}
}
}

Related

Error accessing Names in Excel using Interop

I am programming an application in C# (Visual Studio 2015) and I need to update an .xlsm file.
This file has many formulas, over 1200 names and vba code.
I am using the Interop library and I am able to update some cells and get the relative updated formulas but i have some problem with the Names defined in the Excel.
The program recognizes the names in the Names collection but doesnt let me access some of the names.
When I try to access the value of the cell using its name it produces an exception.
I dont understand why i can access some of the names and others no.
Besides, in the excel, I can see the Name in the combo but when I select it, the cursor doesn't position over the cell.
In my program I could avoid this problem accessing the cells using the reference instead of the Name, but the vba in the excel uses the names and if i open the file from my app it doesnt work.
I am using this code:
excelApplication = new Microsoft.Office.Interop.Excel.Application();
excelApplication.ScreenUpdating = true;
excelApplication.Visible = true;
excelApplication.DisplayAlerts = false;
excelWorkbook = excelApplication.Workbooks.Open(txtFicheroEntrada.Text);
wsDatos = excelWorkbook.Worksheets[1];
wsDatos.Select();
foreach(Microsoft.Office.Interop.Excel.Name v in excelWorkbook.Names)
{
string NombreVar = v.Name;
//here i found the name BobinadoAT correctly. It exists
if (NombreVar == "BobinadoAT" ){ Console.WriteLine(NombreVar); }
}
if (wsDatos.Range["BobinadoAT"] != null) //but here this produces an exception
{
string valorcelda = wsDatos.Range["BobinadoAT"].Value.ToString();
}
¿does anyone work with many excel Names?
¿Am I accessing the names incorrectly?

I want to add new sheet to an existing csv file, but I dont know how to go about it

I want to add new sheet to an existing csv file, but I dont know how to go about it. I already opened the .csv file and i can access each element. so i want to create a new sheet on the existing .csv file and populate the cells with the data from the previous sheet.
class Program
{
static void Main(string[] args)
{
var reader = new StreamReader(File.OpenRead(#"C:\Users\Desktop\test.csv"));
List<string> listA = new List<string>();
List<string> listB = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
//line = line.Skip(1);
var values = line.Split(',');
listA.Add(values[0]);
listB.Add(values[1]);
listA.ForEach(Console.WriteLine);
listB.ForEach(Console.WriteLine);
Console.ReadLine();
}
}
}
I'm going to post this as an answer, even though it's kind of a non-answer. CSV files are simple flat-text files that are comma delimited. There are no higher-level concepts to this file type such as sheets, or cells, workbooks, or formulas.
Since they are just simple text files that are specially formatted, there is no concept of sheets. Instead you can maybe create additional CSV files and name the files accordingly.
If you want to create Excel files, and have individual sheets you can use various libraries or the COM Interops to do this.
COM Interops are for direct connections to Excel natively. Here's a MSDN How-To for Excel. This allows you to create a special object that will allow you to use Excel's API even though it's not a managed API through the .NET Framework.
Here's an example on how to add a sheet in that situation:
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
if (xlApp == null)
{
Console.WriteLine("EXCEL could not be started. Check that your office installation and project references are correct.");
return;
}
xlApp.Visible = true;
Workbook wb = xlApp.Workbooks.Add(XlWBATemplate.xlWBATWorksheet); //adds worksheet to our workbook
Worksheet ws = (Worksheet)wb.Worksheets[1]; //access that worksheet linked into the workbook
if (ws == null)
{
Console.WriteLine("Worksheet could not be created. Check that your office installation and project references are correct.");
}
Another option is to use the Open XML SDK for Office, which can be used for the new Office formats (.xlsx for example). Personally, I've never used this library, but it's similar to Apache POI for the .NET Framework.

apache poi how to disable external reference or external links?

I've been looking on the web for 30 minutes now and can't find any explanation about that. Here is my problem :
I wrote an application with poi to parse some data from 200 excel files or so and put some of it into a new file. I do some cell evaluation with FormulaEvaluator to know the content of the cells before choosing to keep them or not.
Now, when i test it on a test file with only values in the cells, the program works perfectly but when i use it on my pile of files I get this error :
"could not resolve external workbook name"
Is there any way to ignore external workbook references or set up the environment so that it wont evaluate formula with external references?
Because the ones I need don't contain references...
Thank you
Can you not just catch the error, and skip over that cell?
You're getting the error because you've asked POI to evaluate a the formula in a cell, and that formula refers to a different file. However, you've not told POI where to find the file that's referenced, so it objects.
If you don't care about cells with external references, just catch the exception and move on to the next cell.
If you do care, you'll need to tell POI where to find your files. You do this with the setupEnvironment(String[],Evaluator[]) method - pass it an array of workbook names, and a matching array of evaluators for those workbooks.
In order for POI to be able to evaluate external references, it needs access to the workbooks in question. As these don't necessarily have the same names on your system as in the workbook, you need to give POI a map of external references to open workbooks, through the setupReferencedWorkbooks(java.util.Map<java.lang.String,FormulaEvaluator> workbooks) method.
I have done please see below code that is working fine at my side
public static void writeWithExternalReference(String cellContent, boolean isRowUpdate, boolean isFormula)
{
try
{
File yourFile = new File("E:\\Book1.xlsx");
yourFile.createNewFile();
FileInputStream myxls = null;
myxls = new FileInputStream(yourFile);
XSSFWorkbook workbook = new XSSFWorkbook(myxls);
FormulaEvaluator mainWorkbookEvaluator = workbook.getCreationHelper().createFormulaEvaluator();
XSSFWorkbook workbook1 = new XSSFWorkbook(new File("E:\\elk\\lookup.xlsx"));
// Track the workbook references
Map<String,FormulaEvaluator> workbooks = new HashMap<String, FormulaEvaluator>();
workbooks.put("Book1.xlsx", mainWorkbookEvaluator);
workbooks.put("elk/lookup.xlsx", workbook1.getCreationHelper().createFormulaEvaluator());
workbook2.getCreationHelper().createFormulaEvaluator());
// Attach them
mainWorkbookEvaluator.setupReferencedWorkbooks(workbooks);
XSSFSheet worksheet = workbook.getSheetAt(0);
XSSFRow row = null;
if (isRowUpdate) {
int lastRow = worksheet.getLastRowNum();
row = worksheet.createRow(++lastRow);
}
else {
row = worksheet.getRow(worksheet.getLastRowNum());
}
if (!isFormula) {
Cell cell = row.createCell(row.getLastCellNum()==-1 ? 0 : row.getLastCellNum());
cell.setCellValue(Double.parseDouble(cellContent));
} else {
XSSFCell cell = row.createCell(row.getLastCellNum()==-1 ? 0 : row.getLastCellNum());
System.out.println(cellContent);
cell.setCellFormula(cellContent);
mainWorkbookEvaluator.evaluateInCell(cell);
cell.setCellFormula(cellContent);
// mainWorkbookEvaluator.evaluateInCell(cell);
//System.out.println(cell.getCellFormula() + " = "+cell.getStringCellValue());
}
workbook1.close();
myxls.close();
FileOutputStream output_file =new FileOutputStream(yourFile,false);
//write changes
workbook.write(output_file);
output_file.close();
} catch (Exception e) {
e.printStackTrace();
}
}

How to get a value out of an Excel workbook stored in a SharePoint document library?

I have some data that's currently stored in an Excel workbook. It makes sense for the data to be in Excel (in that it's easy to manage, easy to extend, do calcs, etc.) but some of the data there is required by an automated process, so from that point of view it would be more convenient if it were in a database.
To give the information more visibility, workflow, etc. I'm thinking of moving it to SharePoint. Actually turning it into a SharePoint form would be tedious & time-consuming, and then the flexibility/convenience would be lost; instead, I'm thinking of simply storing the current Excel file within a SharePoint library.
My problem then would be: how can the automated process extract the values it needs from the Excel workbook that now lives within the SharePoint library? Is this something that Excel Services can be used for? Or is there another/better way? And even if it can be done, is it a sensible thing to do?
Having gone through something similar, I can tell you it actually isn't that bad getting values out of an Excel file in a document library. I ended up writing a custom workflow action (used within a SharePoint Designer workflow) that reads values out of the Excel file for processing. I ended up choosing NPOI to handle all of the Excel operations.
Using NPOI, you can do something like this:
// get the document in the document library
SPList myList = web.Lists[listGuid];
SPListItem myItem = myList.GetItemById(ListItem);
SPFile file = myItem.File;
using (Stream stream = file.OpenBinaryStream())
{
HSSFWorkbook workbook = new HSSFWorkbook(stream);
HSSFSheet sheet = workbook.GetSheet("Sheet1");
CellReference c = new CellReference("A1");
HSSFRow row = sheet.GetRow(c.Row);
HSSFCell cell = row.GetCell(c.Col);
string cellValue = cell.StringCellValue;
// etc...
}
You could easily put this in a console application as well.
Yes, I am trying to extract a range of cells on several sheets within a workbook. I was able to use some of the code below in a console application and view the data within the command window. Now I need to dump the data to a SQL Table and was looking for some examples on how to accomplish this and make sure I am going down the correct coding path.
Here is a snapshot of the code I am using.
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
using (SPSite site = new SPSite(SPContext.Current.Site.Url))
{
using (SPWeb web = site.RootWeb)
{
SPList docList = web.Lists[__ListId];
SPListItem docItem = docList.GetItemById(__ListItem);
SPFile docFile = docItem.File;
using (Stream stream = docFile.OpenBinaryStream())
{
HSSFWorkbook wb = new HSSFWorkbook(stream);
//loop through each sheet in file, ignoring the first sheet
for (int i = 1; i < 0; i++)
{
NPOI.SS.UserModel.Name name = wb.GetNameAt(i);
String sheet = wb.GetSheetName(i);
NPOI.SS.UserModel.Name nameRange = wb.CreateName();
nameRange.NameName = ("DispatchCells");
//start at a specific area on the sheet
nameRange.RefersToFormula = (sheet + "!$A$11:$AZ$100");
}
wb.Write(stream);
}
}
}
return ActivityExecutionStatus.Closed;
}

reading excel data

How to read Excel data having Number format ;;; ie hidden value in C# using spreadsheet gear.
I am not sure that I understand your question. This code writes the formatted value of a cell, the number format and the unformatted value:
using System;
namespace WriteFormattedCellWithSpreadsheetGear
{
class Program
{
static void Main(string[] args)
{
var workbook = SpreadsheetGear.Factory.GetWorkbook(#"C:\tmp\MyWorkbook.xlsx");
var worksheet = workbook.Worksheets[0];
var a1 = worksheet.Cells["A1"];
// Write the formatted data
Console.WriteLine("Text={0}", a1.Text);
// Write the number format
Console.WriteLine("NumberFormat={0}", a1.NumberFormat);
// Write the raw data
Console.WriteLine("Value={0}", a1.Value);
}
}
}

Resources