Hope you can help.
I'm looking for a way to build an excel sheet range by just passing in some parameters. My method is as follows:
private void TableCellformatting(int rowStart, int rowEnd, char colStart, char colEnd)
{
char temp;
StringBuilder s = new StringBuilder();
excelSheetRange = null;
for (int i = rowStart; i <= rowEnd; i++)
{
temp = colStart;
while (temp <= colEnd)
{
if (s.Length > 0)
s.Append(", ");
s.Append(string.Format("{0}{1}", temp.ToString(), i));
temp++;
}
}
excelSheetRange = excelSheet.get_Range(s.ToString());
excelSheetRange.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter;
}
This runs ok until the excelSheet.get_Range part is called. When I pass in the cell numbers manually, I have to do it like this:
get_Range("A1", "A2" etc...)
Any ideas if this is even possible, or if there is another way?
Thanks!
Use worksheet.range property.
excelSheetRange = excelSheet.Range[excelsheet.Cells[rowstart, colstart], excelsheet.Cells[rowend, colend]];
Related
I am trying to use function COUNTIF at column B (CustomerName) in table "Products". But I get an error.
Can anyone help why I am getting error and how to fix it.
Thank you so much.
void Duplicate()
{
int ketqua = 1;
Double t;
GetActiveExcelFile();
Excel.Worksheet esh = oWB.Worksheets["Order detail"];
long lastRow;
lastRow = esh.Cells[esh.Rows.Count, 2].End(Excel.XlDirection.xlUp).Row;
Excel.Application a = new Excel.Application();
if (lastRow == 55)
for (int i = 2; i <= lastRow; i++)
{
Excel.Range objRange = (Excel.Range)esh.Cells[i, 2];
String strData = objRange.get_Value(System.Type.Missing).ToString(); //get the value cell[i,2]
if (strData != "")
{
t = a.WorksheetFunction.CountIf(esh.get_Range("B2","B55"), strData);
if (t > 1)
{
ketqua = 1;
break;
}
else
ketqua = 0;
}
}
}
Use always objects, or ranges in excel
//t = a.WorksheetFunction.CountIf(esh.get_Range("B2","B55"), strData);
t = a.WorksheetFunction.CountIf(esh.get_Range("B2","B55"), (Excel.Range)esh.Cells[i, 2]);
OS language vs numberformat
use the default numberformat on your system
I believe it is when you created a new Excel.Application. That's what my problem was. You are referencing an already declared worksheet varaible on a new application. I'm new to coding so hopefully that helps.
I have to make a string which consists a string like - AAA0009, and once it reaches AAA0009, it will generate AA0010 to AAA0019 and so on.... till AAA9999 and when it will reach to AAA9999, it will give AAB0000 to AAB9999 and so on till ZZZ9999.
I want to use static class and static variables so that it can auto increment by itself on every hit.
I have tried some but not even close, so help me out thanks.
Thanks for being instructive I was trying as I Said already but anyways you already want to put negatives over there without even knowing the thing:
Code:
public class GenerateTicketNumber
{
private static int num1 = 0;
public static string ToBase36()
{
const string base36 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var sb = new StringBuilder(9);
do
{
sb.Insert(0, base36[(byte)(num1 % 36)]);
num1 /= 36;
} while (num1 != 0);
var paddedString = "#T" + sb.ToString().PadLeft(8, '0');
num1 = num1 + 1;
return paddedString;
}
}
above is the code. this will generate a sequence but not the way I want anyways will use it and thanks for help.
Though there's already an accepted answer, I would like to share this one.
P.S. I do not claim that this is the best approach, but in my previous work we made something similar using Azure Table Storage which is a no sql database (FYI) and it works.
1.) Create a table to store your running ticket number.
public class TicketNumber
{
public string Type { get; set; } // Maybe you want to have different types of ticket?
public string AlphaPrefix { get; set; }
public string NumericPrefix { get; set; }
public TicketNumber()
{
this.AlphaPrefix = "AAA";
this.NumericPrefix = "0001";
}
public void Increment()
{
int num = int.Parse(this.NumericPrefix);
if (num + 1 >= 9999)
{
num = 1;
int i = 2; // We are assuming that there are only 3 characters
bool isMax = this.AlphaPrefix == "ZZZ";
if (isMax)
{
this.AlphaPrefix = "AAA"; // reset
}
else
{
while (this.AlphaPrefix[i] == 'Z')
{
i--;
}
char iChar = this.AlphaPrefix[i];
StringBuilder sb = new StringBuilder(this.AlphaPrefix);
sb[i] = (char)(iChar + 1);
this.AlphaPrefix = sb.ToString();
}
}
else
{
num++;
}
this.NumericPrefix = num.ToString().PadLeft(4, '0');
}
public override string ToString()
{
return this.AlphaPrefix + this.NumericPrefix;
}
}
2.) Make sure you perform row-level locking and issue an error when it fails.
Here's an oracle syntax:
SELECT * FROM TICKETNUMBER WHERE TYPE = 'TYPE' FOR UPDATE NOWAIT;
This query locks the row and returns an error if the row is currently locked by another session.
We need this to make sure that even if you have millions of users generating a ticket number, it will not mess up the sequence.
Just make sure to save the new ticket number before you perform a COMMIT.
I forgot the MSSQL version of this but I recall using WITH (ROWLOCK) or something. Just google it.
3.) Working example:
static void Main()
{
TicketNumber ticketNumber = new TicketNumber();
ticketNumber.AlphaPrefix = "ZZZ";
ticketNumber.NumericPrefix = "9999";
for (int i = 0; i < 10; i++)
{
Console.WriteLine(ticketNumber);
ticketNumber.Increment();
}
Console.Read();
}
Output:
Looking at your code that you've provided, it seems that you're backing this with a number and just want to convert that to a more user-friendly text representation.
You could try something like this:
private static string ValueToId(int value)
{
var parts = new List<string>();
int numberPart = value % 10000;
parts.Add(numberPart.ToString("0000"));
value /= 10000;
for (int i = 0; i < 3 || value > 0; ++i)
{
parts.Add(((char)(65 + (value % 26))).ToString());
value /= 26;
}
return string.Join(string.Empty, parts.AsEnumerable().Reverse().ToArray());
}
It will take the first 4 characters and use them as is, and then for the remainder of the value if will convert it into characters A-Z.
So 9999 becomes AAA9999, 10000 becomes AAB0000, and 270000 becomes ABB0000.
If the number is big enough that it exceeds 3 characters, it will add more letters at the start.
Here's an example of how you could go about implementing it
void Main()
{
string template = #"AAAA00";
var templateChars = template.ToCharArray();
for (int i = 0; i < 100000; i++)
{
templateChars = IncrementCharArray(templateChars);
Console.WriteLine(string.Join("",templateChars ));
}
}
public static char Increment(char val)
{
if(val == '9') return 'A';
if(val == 'Z') return '0';
return ++val;
}
public static char[] IncrementCharArray(char[] val)
{
if (val.All(chr => chr == 'Z'))
{
var newArray = new char[val.Length + 1];
for (int i = 0; i < newArray.Length; i++)
{
newArray[i] = '0';
}
return newArray;
}
int length = val.Length;
while (length > -1)
{
char lastVal = val[--length];
val[length] = Increment(lastVal);
if ( val[length] != '0') break;
}
return val;
}
I have a list of files like so
abc.txt
pas.txt
tempr.txt
What I would like to do is to append english alphabets to theese file names ..
the result should look like this
abc_a.txt
pas_b.txt
tempr_c.txt
This process should continue till the last character (i.e 'z'). if there are more files then the file names would become
abc_a.txt
pas_b.txt
tempr_c.txt
.................
filename_z.txt
anotherfilename_a001.txt
Notice that the counter was again reset to the first character except an integer was attached to it.
This is the code that i have right now. Please note that it is NOT working ..
string alphabets= "abcdefghijklmnopqrstuvwxyz";
List<string> filenames = new List<string>();
filenames.Add("test1.txt");
filenames.Add("newfile.cs");
filenames.Add("test2.txt");
filenames.Add("newfile2.cs");
string currentFileNmae = string.Empty;
foreach(string s in filenames) {
char usedAlphabet = new char();
for(int i = 0;i<=alphabets.Length-1;i+=11) {
usedAlphabet.Dump();
alphabets[i].Dump();
if(usedAlphabet != alphabets[i] )
{
if(currentFileNmae!= s)
{
string.Format("{0}--{1}",s,alphabets[i]).Dump();
usedAlphabet = alphabets[i];
currentFileNmae = s;
}
}
break;
}
}
I am part of a team that's building a file renamer tool for our internal purposes and hence i need this code. This is part of the our enumertation functionality that we have planned.
Please suggest.
thanks
Try starting here:
using System.Diagnostics;
using System.IO;
string filename = #"C:\Foo\Bar.txt";
for (int count = 0; count < 100; count++)
{
char letter = (char)((int)'a' + count % 26);
string numeric = (count / 26) == 0 ? "" : (count / 26).ToString("000");
Debug.Print(Path.GetFileNameWithoutExtension(filename) + "_" + letter + numeric + Path.GetExtension(filename));
}
Substitute your own loop to go through the filenames and use Path to manipulate the pieces/parts of the names.
The renaming, IIRC, can be handled by File.Move. Surround it with a try/catch to implement the name collision logic.
Had no coffee yet, but this should do.
List<string> files = new List<string>();
int charIndex = 0;
int numericIndex = -1;
foreach (var file in files.Select(path => new FileInfo(path)))
{
// Create new Filename - This may needs some tuning
// to really remove only the extension ad the end
// It doesnt take care of things like
// file.bmp.bmp.bmp ...
string newFileName = String.Format("{0}_{1}{2}.{3}",
file.FullName.Replace(file.Extension,String.Empty),
(char)(charIndex++ + 97),
(numericIndex > -1 ? String.Format("{0:D4}", numericIndex) : String.Empty),
file.Extension);
// Rename the File
file.MoveTo(newFileName);
// Increment Counters.
if (charIndex > 25)
{
charIndex = 0;
numericIndex++;
}
}
You can try something like this
const string directory = #"C:\\wherever";
string[] fiNames = new string[]{ "abc", "pas", "etc",};
char[] alphabet = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
int x = 0;
string ending = "";
for(int i = fiNames.Count()-1; i>=0; i--)
{
if(x%26==0)
{
x=0
if( ending=="")
ending="1";
else
ending=(System.Convert.ToInt32(ending)+1).ToString();
}
System.IO.File.Move(directory+fiNames[i], fiNames[i]+alphabet[x].ToString()+ending);
x++;
}
I'm trying to generate 900,000 keys and store them to a db.
Each value has to be 8 chars and different from generated ones.
Here is my code look like, it's doing ok but it's too slow...
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
richTextBox1.Visible = false;
Generate();
}
public int num = 0;
private void Den1()
{
for (int i = 0; i < 900000; i++)
{
string randomStr = RandomString(8);
string textToSearchFor = randomStr;
int index = richTextBox1.Text.IndexOf(textToSearchFor, StringComparison.OrdinalIgnoreCase);
if (index >= 0)
{
MessageBox.Show("Duplicate ignored from 1!");
i--;
}
else
{
richTextBox1.Text += randomStr + "\n";
num++;
}
label1.Text = "" + num;
}
richTextBox1.Visible = true;
}
public void Generate()
{
CheckForIllegalCrossThreadCalls = false;
Thread thread1 = new Thread(Deneme1);
thread1.Start();
}
private string RandomString(int length, string allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
{
if (length < 0) throw new ArgumentOutOfRangeException("length", "length cannot be less than zero.");
if (string.IsNullOrEmpty(allowedChars)) throw new ArgumentException("allowedChars may not be empty.");
const int byteSize = 0x100;
var allowedCharSet = new HashSet<char>(allowedChars).ToArray();
if (byteSize < allowedCharSet.Length) throw new ArgumentException(String.Format("allowedChars may contain no more than {0} characters.", byteSize));
// Guid.NewGuid and System.Random are not particularly random. By using a
// cryptographically-secure random number generator, the caller is always
// protected, regardless of use.
using (var rng = new System.Security.Cryptography.RNGCryptoServiceProvider())
{
var result = new StringBuilder();
var buf = new byte[128];
while (result.Length < length)
{
rng.GetBytes(buf);
for (var i = 0; i < buf.Length && result.Length < length; ++i)
{
// Divide the byte into allowedCharSet-sized groups. If the
// random value falls into the last group and the last group is
// too small to choose from the entire allowedCharSet, ignore
// the value in order to avoid biasing the result.
var outOfRangeStart = byteSize - (byteSize % allowedCharSet.Length);
if (outOfRangeStart <= buf[i]) continue;
result.Append(allowedCharSet[buf[i] % allowedCharSet.Length]);
}
}
return result.ToString();
}
}
}
Well to start with, I would generate them all and then put them into the UI. I also wouldn't use string.IndexOf to find if you've already got a match. Use a HashSet<string>:
HashSet<string> codes = new HashSet<string>();
while (codes.Count < 900000)
{
codes.Add(RandomString(8));
}
// Then do what you want with the codes
You also shouldn't be setting CheckForIllegalCrossThreadCalls to false. Just generate them all in the background and then use Invoke to get to the UI thread to update your UI. If you really want to update as you go, you could do so periodically... although I wouldn't put them all into a single text box.
Next, I'd look at the RandomString method. Do you really need to create a new RNGCryptoServiceProvider on every iteration? Why not create one and then reuse it?
Likewise, why bother creating a new HashSet<char> and calling ToArray on every call? It sounds like you should probably have a separate class as a RandomCodeGenerator which remembers:
The size of code you're generating
The random number generator
The allowed characters
That will let you get away from doing a lot of setup work on every iteration.
I'd then personally create a char[] of the right size and just iterate until you've filled it, then create a string from that... I don't see the need for StringBuilder... but that's probably not hurting you.
You could use a Guid to quickly generate your keys:
Guid guid = Guid.NewGuid();
string theString = guid.ToString().Replace("-", string.Empty).Substring(0, 8).ToUpperInvariant();
You could do that directly in SQL, like: https://stackoverflow.com/a/9631898/403335
But even if you do that with code, I would fill a container with a sequence of all the possible values.
Then randomly select elements from the sequence container, use the element and delete it from the container. This way you will surely get all the numbers, without wasting time in finding a "hole" number (not already picked up).
In code:
Random random = new Random();
List<string> uniqueStrings = new List<string>(900000);
List<string> randomString = new List<string>(900000);
for (char c1 = 'A'; c1 <= 'Z'; ++c1)
for (char c2 = 'A'; c2 <= 'Z'; ++c2)
for (char c3 = 'A'; c3 <= 'Z'; ++c3)
for (char c4 = 'A'; c4 <= 'Z'; ++c4)
for (char c5 = 'A'; c5 <= 'Z'; ++c5)
for (char c6 = 'A'; c6 <= 'Z'; ++c6)
for (char c7 = 'A'; c7 <= 'Z'; ++c7)
for (char c8 = 'A'; c8 <= 'Z'; ++c8)
uniqueStrings.Add(string.Format("{0}{1}{2}{3}{4}{5}{6}{7}", c1, c2, c3, c4, c5, c6, c7, c8));
for (int i = 0; i < uniqueStrings.Count; i++)
{
const int index = random.Next(uniqueStrings.Count) + 1;
randomString.Add(uniqueStrings[index]);
uniqueStrings.RemoveAt(index);
}
First of all RichTextBox is not an appropriate value store. The IndexOf method of the TextBox is most likely the slowest part of your code you need to replace it with something else, I would rather use a HashSet<string> to figure out of there are duplicates.
I think this code may be helpful
public static string GeneratePassword()
{
string strPwdchar = "abcdefghijklmnopqrstuvwxyz0123456789#+#&$ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string strPwd = "";
Random rnd = new Random();
for (int i = 0; i <= 7; i++)
{
int iRandom = rnd.Next(5, strPwdchar.Length - 1);
strPwd += strPwdchar.Substring(iRandom, 1);
}
return strPwd;
}
Iterate it 90,000 times on a mouse click event.....I hope things will work
Have a look at this discussion.
My preferred solution, which I use for generating +100.000 unique strings is the linked answer
_documentContent contains the whole document as html view source.
patternToFind contains text to be searched in _documentContent.
Code snippet below works fine if language is English.
The same code however doesn't works at all when it encounters a language like Korean.
Sample Document
Present Tense
The present tense is just as you have learned. You take the dictionary form of a verb, drop the 다, add the appropriate ending.
먹다 - 먹 + 어요 = 먹어요
마시다 - 마시 + 어요 - 마시어요 - 마셔요.
This tense is used to represent what happens in the present. I eat. I drink. It is a general term for the present.
When I am trying to find 먹 the code belows fails.
can someone please suggest some solution to this
using System;
using System.Collections.Generic;
using System.Text;
namespace MultiByteStringHandling
{
class Program
{
static void Main(string[] args)
{
string _documentContent = #"먹다 - 먹 + 어요 = 먹어요";
byte[] patternToFind = Encoding.UTF8.GetBytes("먹");
byte[] DocumentBytes = Encoding.UTF8.GetBytes(_documentContent);
int intByteOffset = indexOf(DocumentBytes, patternToFind);
Console.WriteLine(intByteOffset.ToString());
}
public int indexOf(byte[] data, byte[] pattern)
{
int[] failure = computeFailure(pattern);
int j = 0;
if (data.Length == 0) return 0;
for (int i = 0; i < data.Length; i++)
{
while (j > 0 && pattern[j] != data[i])
{
j = failure[j - 1];
}
if (pattern[j] == data[i])
{
j++;
}
if (j == pattern.Length)
{
return i - pattern.Length + 1;
}
}
return -1;
}
/**
* Computes the failure function using a boot-strapping process,
* where the pattern is matched against itself.
*/
private int[] computeFailure(byte[] pattern)
{
int[] failure = new int[pattern.Length];
int j = 0;
for (int i = 1; i < pattern.Length; i++)
{
while (j > 0 && pattern[j] != pattern[i])
{
j = failure[j - 1];
}
if (pattern[j] == pattern[i])
{
j++;
}
failure[i] = j;
}
return failure;
}
}
}
Seriously, why not just do the following?
var indexFound = documentContent.IndexOf("data");
Converting strings into byte arrays and then searching those doesn't make much sense to me when you're original data is text. You can always find the byte position after if you wish.
UTF-8 is a variable multi-byte format. Searching for English text in Korean data will never match on a direct pattern match. If you are scanning text you would be much better off using .IndexOf(pattern) [as Noldorin pointed out] or .Contains(pattern).