Maximum String Length of PrintArea in Excel - c#

What is the maximum string length of PrintArea in Excel 2003 and 2010?
I have a PrintArea string length of 677.
This throws an error in Excel 2003, but not in 2010, so I'd like to know what the maximum string length is in both versions as well as 2007.

The limit in 2003 and 2007 is 255 characters.
I don't have a copy of 2010 to test, but you can use this VBA code to test it easily. Just run the macro and after it crashes, go to Debug, and check the value of i. One less than that will be the maximum string length.
Sub PrintRangeTest()
Dim i As Integer
Dim j As Integer
Dim newName As String
newName = ""
Dim rng As Range
For i = 1 To 100000 //some arbitrarily large number
newName = ""
For j = 1 To i
newName = newName & "a"
Next
Set rng = ActiveSheet.Range(Cells(1, 1), Cells(i, i))
rng.Name = newName
ActiveSheet.PageSetup.PrintArea = rng
Next
End Sub

Related

Leading 0 is dropped from excel data cells populated from VB

In my vb Windows Application Program I use this code to create excel report:
Public Sub CreateExcelFile(ByVal InputDataTable As DataTable, ByVal FileName As String)
Dim ExcelApp As New Microsoft.Office.Interop.Excel.ApplicationClass
Dim ExcelWorkbook As Microsoft.Office.Interop.Excel.Workbook = Nothing
Dim ExcelWorkSheet As Microsoft.Office.Interop.Excel.Worksheet = Nothing
Dim ColumnIndex As Integer = 0
Dim RowIndex As Integer = 1
Try
ExcelWorkbook = ExcelApp.Workbooks.Add()
ExcelWorkSheet = ExcelWorkbook.ActiveSheet()
For Each c As DataColumn In InputDataTable.Columns
ColumnIndex += 1
ExcelApp.Cells(RowIndex, ColumnIndex) = c.ColumnName
Next
For Each r As DataRow In InputDataTable.Rows
RowIndex += 1
ColumnIndex = 0
For Each c As DataColumn In InputDataTable.Columns
ColumnIndex += 1
ExcelApp.Cells(RowIndex, ColumnIndex) = r(c.ColumnName).ToString
Next
Next
ExcelWorkSheet.Columns.AutoFit()
ExcelWorkbook.SaveAs(FileName)
ExcelWorkbook.Close()
ExcelApp.Quit()
Catch ex As Exception
MsgBox("Err", MsgBoxStyle.Information + MsgBoxStyle.MsgBoxRtlReading)
Finally
ExcelApp = Nothing
ExcelWorkbook = Nothing
ExcelWorkSheet = Nothing
ColumnIndex = Nothing
RowIndex = Nothing
End Try
End Sub
if I have a code or telephone number that has a 0 as the first character, it does not show in excel file . I use this code to solve the problem:
ExcelWorkSheet.Activate()
ExcelWorkSheet.Cells().Columns.NumberFormat = "#"
ExcelWorkSheet.Cells().EntireColumn.NumberFormat = "#"
but it doesn't work. I read this question but cannot solve my problem:
Format an Excel column (or cell) as Text in C#?
Set data type like number, text and date in excel column using Microsoft.Office.Interop.Excel in c#
Insert DataTable into Excel Using Microsoft Access Database Engine via OleDb
Setting the format of a cell after you have data in it does not always work because some data may have been lost on entry in the conversion to the original data format. Make sure you set the format of the cell first so that any leading zeros do not get truncated.

C# + Excel. NamedRange.Formula

Is there a limit on the length of the formula?
If I use:
string form = "=ЕСЛИ(ЛЕВСИМВ(C2;3)=\"101\";\"цту\";ЕСЛИ(ЛЕВСИМВ(C2;3)=\"102\";\"сзту\";ЕСЛИ(ЛЕВСИМВ(C2;3)=\"103\";\"юту\";ЕСЛИ(ЛЕВСИМВ(C2;3)=\"104\";\"пту\";ЕСЛИ(ЛЕВСИМВ(C2;3)=\"105\";\"уту\";ЕСЛИ(ЛЕВСИМВ(C2;3)=\"106\";\"сту\";ЕСЛИ(ЛЕВСИМВ(C2;3)=\"107\";\"двту\";\"скту\")))))))";
xlWorkSheet.Range["D2"].FormulaLocal = form;
That's all okay.
But if I use:
string form = "=ЕСЛИ(ЛЕВСИМВ(C2;3)=\"101\";\"цту\";ЕСЛИ(ЛЕВСИМВ(C2;3)=\"102\";\"сзту\";ЕСЛИ(ЛЕВСИМВ(C2;3)=\"103\";\"юту\";ЕСЛИ(ЛЕВСИМВ(C2;3)=\"104\";\"пту\";ЕСЛИ(ЛЕВСИМВ(C2;3)=\"105\";\"уту\";ЕСЛИ(ЛЕВСИМВ(C2;3)=\"106\";\"сту\";ЕСЛИ(ЛЕВСИМВ(C2;3)=\"107\";\"двту\";ЕСЛИ(ЛЕВСИМВ(C2;3)=\"108\";\"скту\";\"fuck\"))))))))";
xlWorkSheet.Range["D2"].FormulaLocal = form;
That error takes off:
HRESULT: 0x800A03EC
It seems there is a limit to the length of string written to .FormulaLocal (and other forms of .Formula)
By experimentation in VBA, it apears to be 258 characters. I can find some references on various blogs to this suggesting a limit of about 256, but can find an official source.
Interestingly, this limit doesn't apply if the string doesn't include a = prefix.
Tested on Excel 2010.
For completness, here's the test code
Sub Demo()
Dim s As String, ss As String, f As String
Dim r As Range
Dim i As Long
Set r = [A20]
s = "=""This is a test of string length: "
ss = "z"
On Error GoTo EH
For i = 1 To 350
f = s & ss & """"
Debug.Print ""
Debug.Print Len(f)
r.FormulaLocal = f
Debug.Print "OK"
ss = "z" & ss
Next
Exit Sub
EH:
Debug.Print "Fail"
End Sub
And the last few lines of the result
257
OK
258
OK
259
Fail
It gets weirder: this code works
Sub Demo()
Dim s As String, ss As String, f As String
Dim r As Range
Dim i As Long
Set r = [A20]
s = "IF(A1=1,AAA999,FALSE)"
ss = "z"
r.FormulaLocal = "=" & s
On Error GoTo EH
For i = 1 To 60
Debug.Print ""
Debug.Print Len(r.FormulaLocal)
r.FormulaLocal = Replace(r.FormulaLocal, "AAA999", s)
Debug.Print "OK"
Debug.Print Len(r.FormulaLocal)
Next
Exit Sub
EH:
Debug.Print "Fail"
End Sub
What this does is builds up the formula up in sections, each as a valid Formula in its own right. Fails at about 1000 characters (1024 maybe).
Check the following page for the Excel limits:
https://support.office.com/en-nz/article/Excel-specifications-and-limits-1672b34d-7043-467e-8e27-269d656771c3
In particular, it says:
Length of formula contents - 8,192 characters
Internal length of formula - 16,384 bytes

How to get Nth number from the specific position of a number in a string - Regex

288007 327920 374740 000368 044575 082865 680798
717374 755879 811106 855460 920577 953515 996819 ......
I have a string containing thousands of 6-digit numbers and I want to extract the Nth numbers after Nth number with the help of regular expression.
Let say I need to extract Three numbers after the 4th number then The result should be 044575 082865 680798.
another example If I need to extract 2 numbers after the 10th number then the result should be 855460 920577.
I don't know is this possible with regex, I think FOR EACH statement may be use in my case.
I am only able to extract each six digits number with the code below.
Dim NumberMatchCollection As MatchCollection = Regex.Matches("String containing numbers", "(?<!\d)\d{6}(?!\d)")
For Each NumberMatch As Match In NumberMatchCollection
Dim ItemNumber As String = NumberMatch.Value
Next
Edited:
I can not guarantee that every separator character will be a single space, a double space, a tab or something else. I can just guarantee that the number length always will be 6 which will be separated by space(s) or tab(s).
Wouldn't this be simpler using maths?
Three numbers after the 4th number, is chars (7 * 4) + (7 * 3)
To expand on my comment. This assume that the actual data are divided equaly.
If each number have 6 digits with a space in between. Then the position of the 4th number will be (6+1)*4 and if you want 3 numbers than you just need to fetch (6+1)*3 amount of characters.
Dim str As String
str = "288007 327920 374740 000368 044575 082865 680798 717374 755879 811106 855460 920577 953515 996819"
Dim startingNumber As Integer = 4
Dim amountToFetch As Integer = 3
' 7 = [size of each number] + [delimiter length]
' 7 = 6 + 1
Console.WriteLine(str.Substring(7 * startingNumber, 7 * amountToFetch))
Console.ReadLine()
If you would like a regex and c# solution, the following code does the 3 numbers after 4th number example.
var st = #"288007 327920 374740 000368 044575 082865 680798
717374 755879 811106 855460 920577 953515 996819";
var pattern = #"^(\d+\s+){4}((?<x>\d+)\s+){3}";
var matches = Regex.Matches(st,pattern,RegexOptions.Singleline);
foreach (Capture m in matches[0].Groups["x"].Captures)
Console.WriteLine("value={0}", m.Value);
(Edit: removed one group per comment below)
You can .Split() the string and use LINQ extension methods on the resulting array:
// some test data...
var rand = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 10000; i++)
{
sb.Append(i.ToString("000000") + ((rand.Next(5)==1) ? " ": "\t"));
}
string s = sb.ToString();
string portion = string.Join(" ", s.Split(new [] {' ', '\t'}, StringSplitOptions.RemoveEmptyEntries).Skip(10).Take(3));
Console.WriteLine(portion); // outputs "000011 000012 000013"
Note: for the first number you would .Skip(0).
But if your string is in the rigid format you show (asuming the variable numbers of spaces are typos, thanks #ErikE), Coenraad's method of calculating where the start of the required string is and how many characters to take would be more efficient. I'll leave it to Coenraad to expand on that answer as it would not be fair to possibly take the points.
I tried and tried to make the regex method be consistently fast, but I found it depended strongly on which numbers you want to retrieve:
For anyone wanting to test that, I put a default Chart on a Form and used this code:
Imports System.Text
Imports System.Text.RegularExpressions
Imports System.Windows.Forms.DataVisualization
Imports System.Windows.Forms.DataVisualization.Charting
Public Class Form1
Sub DoStuff()
Dim ser1 As New Series With {.Name = "String.Split"}
Dim ser2 As New Series With {.Name = "RegEx"}
Dim sb As New StringBuilder()
For i As Integer = 1 To 10000
sb.Append(i.ToString("000000") + " ")
Next
Dim s As String = sb.ToString()
Dim sw As New Stopwatch()
Dim itemsToTake As Integer = 50
For firstItem = 1 To 9000 Step 100
sw.Restart()
Dim portion As String = String.Join(" ", s.Split({" "c}, StringSplitOptions.RemoveEmptyEntries).Skip(firstItem - 1).Take(itemsToTake))
sw.Stop()
ser1.Points.AddXY(firstItem -1, sw.ElapsedTicks)
Dim pattern = "^(?:\d+\s+){" + (firstItem - 1).ToString() + "}((\d+)\s+){" + itemsToTake.ToString() + "}"
Dim re = New Regex(pattern)
sw.Restart()
Dim matches = re.Matches(s)
Dim cs = matches(0).Groups(0).Captures
sw.Stop()
ser2.Points.AddXY(firstItem - 1, sw.ElapsedTicks)
Next
Chart1.Series.Clear()
Chart1.Series.Add(ser1)
Chart1.Series(0).ChartType = SeriesChartType.Line
Chart1.Series.Add(ser2)
Chart1.Series(1).ChartType = SeriesChartType.Line
Chart1.ChartAreas(0).AxisX.IsMarginVisible = False
Chart1.ChartAreas(0).AxisX.Title = "First item to retrieve"
Chart1.ChartAreas(0).AxisY.Title = "Time taken"
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
DoStuff()
End Sub
End Class

Importing from CSV to DataGridView without Scientific formatted numbers

I have a function which successfully loads data from a CSV to a datagridview. The problem is that there are very long numbers in some columns and they appear such as 5.00E+14. Ideally, I would like to change that value in the CSV file because I'm planning to export the CSV to another database. Any ideas?
Dim Lines As String() = File.ReadAllLines(sFile)
Dim Fields As String()
Fields = Lines(0).Split(New Char() {","c})
Dim Cols As Integer = Fields.GetLength(0)
Dim dt As New DataTable()
'1st row must be column names; force lower case to ensure matching later on.
For i As Integer = 0 To Cols - 1
dt.Columns.Add(Fields(i).ToLower(), GetType(String)).AllowDBNull = True
Next
Dim Row As DataRow
' = 1 to skip the first line
For i As Integer = 1 To Lines.GetLength(0) - 1
Fields = Lines(i).Split(New Char() {","c})
Row = dt.NewRow()
For f As Integer = 0 To Cols - 1
Row(f) = Fields(f)
Next
dt.Rows.Add(Row)
Next
DataGridView2.DataSource = dt
You would need to change the formatting in the destination cells, either manually or using
Range("F7:G32").NumberFormat = "0.00"
with whatever range and number format you want to use. You can't change it in the csv file, because no matter how the number comes in, with the default general formatting in excel, it will display long numbers in scientific format.

Extracting data from excel using interop - ignore certain cells where no data is contained

I'm using c# and visual studio to extract data from an excel sheet, put it into an array (adding commas to the end of each string) and then output it to a .CSV file.
Now I've run into a snag that occurs when a cell has either no data, or not the data expected (i.e. an image).
I am assuming that this is on the reading end of the excel sheet, rather than the output to .CSV as when I get this error, I'm not getting any data put into the array.
Here's a snippet of the code that I'm using which has been adapted from a Microsoft example on accessing Excel data using interop.
//Get a range of data.
range = objSheet.get_Range(ranges1, ranges2);
//Retrieve the data from the range.
Object[,] saRet;
saRet = (System.Object[,])range.get_Value(Missing.Value);
//Determine the dimensions of the array.
long iRows;
long iCols;
iRows = saRet.GetUpperBound(0);
iCols = saRet.GetUpperBound(1);
//Build a string that contains the data of the array.
String valueString;
valueString = "Prices";
System.IO.StreamWriter OutWrite = new System.IO.StreamWriter("h:\\out.csv");
for (long rowCounter = 1; rowCounter <= iRows; rowCounter++)
{
for (long colCounter = 1; colCounter <= iCols; colCounter++)
{
//Write the next value into the string.
valueString = String.Concat(valueString,
saRet[rowCounter, colCounter].ToString() + ", ");
}
//Write in a new line.
valueString = String.Concat(valueString, "\n");
}
The error that I recieve is to do with the system.object line is:
Error: Object reference not set to an instance of an object, Line: WindowsFormApplication2
(No I haven't gotten around to renaming my project yet :P )
Cheers, Andy.
This line is dangerous:
valueString = String.Concat(valueString, saRet[rowCounter, colCounter].ToString() + ", ");
...as the result from saRet[rowCounter, colCounter] could be null. If an empty string is acceptable for an empty cell, use Convert.ToString(), which will interpret nulls as empty strings:
valueString = String.Concat(valueString, Convert.ToString(saRet[rowCounter, colCounter]) + ", ");
I suspect this is why you are getting the NullReferenceException.

Categories