Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# .NET
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.89/9: Рейтинг темы: голосов - 9, средняя оценка - 4.89
phobos_nik
2 / 2 / 0
Регистрация: 13.05.2011
Сообщений: 20
1

Из файла Excel прочитать даты рождения людей и сравнить с текущей

02.11.2012, 21:09. Просмотров 1606. Ответов 8
Метки нет (Все метки)

Вкратце ситуация такова: необходимо из .xls файла прочитать даты рождения людей и сравнить с текущей. Т.е., грубо говоря, определить когда у человека из списка в текущем году будет день рождения.

Формат даты в ячейках дд.ММ.гггг, при этом год рождения учитывать не надо (первая мысль - сравнивать строки, образуемые из данных ячейки и текущей даты). Код ниже не выполняет необходимых действий.

C#
1
2
3
4
5
6
7
8
9
10
11
12
workbook = app.Workbooks.Open(@"путь к файлу");
worksheet = workbook.ActiveSheet;
search_birthdate = worksheet.get_Range("D1", "D" + Convert.ToString(worksheet.Columns.Count));
int i = 0;
int count = 0;
 
for (i = 1; i <= worksheet.Columns.Count; i++)
{
DateTime dt = DateTime.FromOADate((double)search_birthdate.Cells[i].Value2);
if (dt.ToString("dd.MM") == DateTime.Now.ToString("dd.MM"))
count++;
}
Код
C#
1
DateTime dt = DateTime.FromOADate((double)search_birthdate.Cells[i].Value2);
для работы с прочитанными из таблицы данными взят отсюда и переработан в соответствии с обстоятельствами программы.

Что характерно, следующие фрагменты кода возвращают на вид одинаковые значения, но их сравнение не дает никакого результата:

C#
1
search_birthdate.Cells[445].Value.ToString("dd.MM")
и
C#
1
DateTime.Now.ToString("dd.MM"))
.

Т.е.
C#
1
2
3
4
5
6
7
8
int i = 0;
int count = 0;
 
for (i = 1; i <= worksheet.Columns.Count; i++)
{
if search_birthdate.Cells[i].Value.ToString("dd.MM") == DateTime.Now.ToString("dd.MM"))
count++;
}
не дает инкремента счетчика count, несмотря на то, что
  • итерация по search_birthdate должна происходить (проверял инкрементом в цикле при отсутствии всяких условий - количество строк возвращается верное),
  • в search_birthdate существует значение, совпадающее с выводом
    C#
    1
    
    DateTime.Now
.

Подозреваю, что дело как-то заключается в приведении типов, но по причине своего нубства в точной причине не уверен и как решить проблему - не подозреваю.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.11.2012, 21:09
Ответы с готовыми решениями:

Сравнение даты с текущей
Еще раз здравствуйте. Столкнулся еще с одной проблемой. Суть: В таблице...

Сравнить значение текущей даты с датой из БД
добрый день, подскажите пожалуйста как мне проверить значение даты...

Запись текущей даты в файл
Пытаюсь записать текущую дату в таблицу БД. Делаю так:SqlConnection sqlcon =...

Поиск даты рождения
Привет! Как выполнить поиск по бд(SQL) если DateTime.Today = дате рождения...

От текущей даты отнять 24 часа
Как в sql от текущей даты(getdate()) отнять 24 часа???

8
xZooYx
120 / 101 / 9
Регистрация: 12.06.2012
Сообщений: 318
Записей в блоге: 12
03.11.2012, 05:01 2
Попробуйте для начала проверить, а ваш цикл for вообще выполняется.
Если да, то проверьте, возвращает ли строка
C#
1
search_birthdate.Cells[i].Value.ToString("dd.MM")
хоть один результат, равный сегодняшнему значению
C#
1
DateTime.Now.ToString("dd.MM"))
0
phobos_nik
2 / 2 / 0
Регистрация: 13.05.2011
Сообщений: 20
03.11.2012, 20:56  [ТС] 3
Нашёл у себя ошибку: поскольку значения одного поля записаны по столбцам, то и цикл с областями поиска должен осуществляться по строкам. Т.Е. вместо
C#
1
worksheet.Columns.Count
надо использовать
C#
1
worksheet.Rows.Count
.

Решил упростить цикл до минимального: в листе 715 заполненных строк, соответственно
C#
1
2
3
4
5
6
7
            for (i = 1; i <= 715; i++)
            {
                if (search_departament.Cells[i].Value2 == "строка для выборки по подразделению")
                    //if (search_birthdate.Cells[i].Value2.ToString("dd.MM") == DateTime.Now.ToString("dd.MM"))
                            count++;
            }
            label1.Text = Convert.ToString(count);
цикл возвращает верное значение записей по указанному подразделению.

Если же раскомментировать условие поиска по дате в том виде, в котором оно указано выше - то цикл ничего не возвращает (условие поиска по подразделению закомментировано, совпадение текущей даты и даты рождения в таблице есть - 1 штука). По идее цикл должен вернуть "1", но ничего не происходит.

P.S. Категории поиска тоже упростил для нормального восприятия:
было
C#
1
search_birthdate = worksheet.get_Range("D1", "D" + Convert.ToString(worksheet.Columns.Count));
стало
C#
1
worksheet.get_Range("D1", "D715");
Добавлено через 6 часов 35 минут
После работы над ошибками в сухом остатке имеется следующий код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
app = new Excel.Application(); 
app.Visible = true;
 
workbook = app.Workbooks.Open(@"путь к файлу");
worksheet = workbook.ActiveSheet;
 
int i = 0;
int count = 0;
 
label1.Text += "\n" + DateTime.Now.ToString("dd.MM");//вывод текущей даты в формате dd.MM
label1.Text += "\n" + worksheet.Cells[1][номер строки в таблице].Value;//вывод ФИО
label1.Text += "\n" + worksheet.Cells[2][номер строки в таблице].Value;//вывод должности
label1.Text += "\n" + worksheet.Cells[3][номер строки в таблице].Value;//вывод подразделения
label1.Text += "\n" + worksheet.Cells[4][номер строки в таблице].Value.ToString("dd.MM");//вывод даты рождения в формате dd.MM
 
label1.Text += "\n" + worksheet.UsedRange.Rows.Count;//вывод количества строк в таблице
 
for (i = 1; i <= worksheet.UsedRange.Rows.Count; i++)
       count++;
       //if (worksheet.Cells[3][i].Value == "название подразделения")
       //if (worksheet.Cells[4][i].Value.ToString("dd.MM") == DateTime.Now.ToString("dd.MM"))
 
label1.Text += "\n" + count;
Вывод
C#
1
2
3
4
5
6
7
label1.Text += "\n" + DateTime.Now.ToString("dd.MM");//вывод текущей даты в формате dd.MM
label1.Text += "\n" + worksheet.Cells[1][номер строки в таблице].Value;//вывод ФИО
label1.Text += "\n" + worksheet.Cells[2][номер строки в таблице].Value;//вывод должности
label1.Text += "\n" + worksheet.Cells[3][номер строки в таблице].Value;//вывод подразделения
label1.Text += "\n" + worksheet.Cells[4][номер строки в таблице].Value.ToString("dd.MM");//вывод даты рождения в формате dd.MM
 
label1.Text += "\n" + worksheet.UsedRange.Rows.Count;//вывод количества строк в таблице
соответствует действительности и записям в таблице в соответствующих ячейках, возвращаемое значение счетчика из цикла соответствует количеству заполненных строк.

Условие
C#
1
if (worksheet.Cells[3][i].Value == "название подразделения")
возвращает правильное количество записей сотрудников нужного подразделения.

При использовании только условия
C#
1
if (worksheet.Cells[4][i].Value.ToString("dd.MM") == DateTime.Now.ToString("dd.MM"))
счетчик из цикла возвращает пустую строку, т.е. ничего.

Просьба помочь разобраться в причинах этого явления и составить верное условие.

Добавлено через 38 минут
Таки да, код
C#
1
dates = (worksheet.Cells[4][номер записи].Value.ToString("dd.MM") == DateTime.Now.ToString("dd.MM"));
обращает булевскую переменную dates в false.
При этом сегодня человек из этой записи справляет день рождения, по отдельности куски
C#
1
worksheet.Cells[4][номер записи].Value.ToString("dd.MM")
и
C#
1
DateTime.Now.ToString("dd.MM")
дают значение "03.11" каждый в тестовом выводе в начале исправленного кода.

Есть ли у форумчан какие-нибудь соображения по этому поводу?
0
Eva_yk
43 / 43 / 18
Регистрация: 15.03.2009
Сообщений: 178
05.11.2012, 11:13 4
C#
1
2
3
4
5
6
string str = worksheet.Cells[4][i].Value.ToString();
//сначала преобразуем в формат даты:
DateTime dt1 = Convert.ToDateTime(str);
DateTime dt2 = DateTime.Now;
//и потом можно сравнивать:
if (dt1.ToString("dd.MM") == dt2.ToString("dd.MM")) ...
1
phobos_nik
2 / 2 / 0
Регистрация: 13.05.2011
Сообщений: 20
05.11.2012, 13:19  [ТС] 5
Цитата Сообщение от Eva_yk Посмотреть сообщение
C#
1
2
3
4
//сначала преобразуем в формат даты:
DateTime dt1 = Convert.ToDateTime(str);
DateTime dt2 = DateTime.Now;
//и потом можно сравнивать:
Огромное спасибо!

Самое интересное, что такой вариант работает, правда я сделал чуть-чуть по другому:
C#
1
2
string birthdate = worksheet.Cells[4][i].Value.ToString("dd.MM");
if (birthdate == DateTime.Now.ToString("dd.MM"))
Возникает закономерный (на мой взгляд) вопрос: а почему не работает сравнение непосредственно выражений (ведь, судя по всему, они дают визуально одинаковый строковый вывод), зачем нужны подобные костыли в виде дополнительных переменных? Знает ли кто-то из форумчан ответ?
0
phobos_nik
2 / 2 / 0
Регистрация: 13.05.2011
Сообщений: 20
05.11.2012, 19:02  [ТС] 6
Цитата Сообщение от Eva_yk Посмотреть сообщение
C#
1
2
3
string str = worksheet.Cells[4][i].Value.ToString();
//сначала преобразуем в формат даты:
DateTime dt1 = Convert.ToDateTime(str);
Пожалуй я забыл упомянуть, что в 4-м столбце даты рождения хранятся в формате дат в виде dd.MM.yyyy

Наверняка поэтому переводы данных из формата представления даты в строковый вид и обратно особо эффекта не дают.

Собственно вариант, предложенный Eva_yk эффекта не дал: для иллюстрации предоставляю скриншоты вывода проги. Из них видно, что само по себе условие
C#
1
(worksheet.Cells[4][607].Value.ToString("dd.MM") == DateTime.Now.ToString("dd.MM"))
выполняется вне тела цикла, но в цикле (где теоретически count должен увеличиться на 1 - больше совпадений в таблице нет), судя по всему, условие не выполняется.
Более того, в том случае, когда в цикле в любом виде осуществляется сравнение дат из таблицы с текущей, счетчик вообще не возвращается. Причины подобного явления мне неизвестны, но очень хотелось бы их узнать.

Обработка же только сравнения по подразделениям возвращает из цикла вполне вменяемое значение счетчика.

Первый прилепленный скриншот отображает текст проги с результатом выполнения в случае наличия в цикле предложенного Eva_yk варианта поиска по датам (без возвращаемого значения счетчика). Второй скриншот отображает текст проги с результатом выполнения в случае наличия в цикле только поиска совпадений по названию подразделения (значение счетчика возвращается).

P.S. Размытия имен личностей и названий подразделений, а также пути к файлу сделаны на всякий случай, поскольку эти данные не имеют решающего значения для решения проблемы. Но тем не менее, они вполне себе нормально читаются из таблицы.
0
Миниатюры
Из файла Excel прочитать даты рождения людей и сравнить с текущей   Из файла Excel прочитать даты рождения людей и сравнить с текущей  
xZooYx
120 / 101 / 9
Регистрация: 12.06.2012
Сообщений: 318
Записей в блоге: 12
05.11.2012, 21:28 7
Ну так, чисто в качестве бреда... Попробуйте поставить точку останова в цикле (где у вас условие), проверить цикл вообще выполняется?
Или присвоить какой то переменной значение строки worksheet.UsedRange.Rows.Count и использовать в цикле эту переменную вместо цепочки свойств.
0
phobos_nik
2 / 2 / 0
Регистрация: 13.05.2011
Сообщений: 20
11.11.2012, 13:55  [ТС] 8
xZooYx, совет дал результат, после длительного шаманства с переменными и точками останова был найден рабочий вариант:
C#
1
2
3
4
5
6
string current_date = DateTime.Now.ToString("dd.MM");
for (i = 1; i <= worksheet.UsedRange.Rows.Count; i++)
{
string birthday = worksheet.Cells[4][i].Value.ToString("dd.MM");
     if (birthday == current_date)
}
В таком случае условие срабатывает нормально, цикл выполняется.
Всем отписавшимся в теме огромное спасибо за помощь!!!

P.S. Вопрос , почему
Цитата Сообщение от phobos_nik Посмотреть сообщение
следующие фрагменты кода возвращают на вид одинаковые значения, но их сравнение не дает никакого результата:
C#
1
search_birthdate.Cells[445].Value.ToString("dd.MM")
и
C#
1
DateTime.Now.ToString("dd.MM"))
Если я верно понимаю логику происходящего, то в цикле либо не осуществлялось преобразование чего-то из вышеперечисленного в строку, либо неадекватно выполнялась проверка выполнения условия.
С моей точки зрения, следующие фрагменты кода эквивалентны
  1. C#
    1
    2
    3
    4
    5
    6
    
    string current_date = DateTime.Now.ToString("dd.MM");
    for (i = 1; i <= worksheet.UsedRange.Rows.Count; i++)
    {
    string birthday = worksheet.Cells[4][i].Value.ToString("dd.MM");
         if (birthday == current_date)
    }
  2. C#
    1
    2
    
    for (i = 1; i <= worksheet.UsedRange.Rows.Count; i++)
         if (worksheet.Cells[4][i].Value.ToString("dd.MM") == DateTime.Now.ToString("dd.MM"))
но VS 2012, судя по всему, имеет точку зрения, отличную от моей.
Внимание вопрос:
Кто-нибудь знает причину происходящего?
Ибо компьютер по определению существо неодушевленное, и его точка зрения всегда обусловлена чем-то реальным, а не комбинацией звезд на небе и прочей чепухой.

P.P.S. На усмотрение модераторов - либо закрыть эту тему, ибо проблема решена, либо оставить открытой до появления в ней внятного ответа на поставленный в постскриптуме вопрос. Заранее благодарю за внимание и понимание.
0
xZooYx
120 / 101 / 9
Регистрация: 12.06.2012
Сообщений: 318
Записей в блоге: 12
12.11.2012, 10:11 9
Думаю проблема в том, что при вот сравнении:
C#
1
if (worksheet.Cells[4][i].Value.ToString("dd.MM") == DateTime.Now.ToString("dd.MM"))
одно из значений (или даже оба) приводилось к типу object (т.е. строка, полученная, как результат метода ToString, приводилась к object).
Если не сложно попробуйте сравнить строки через метод Equals вот в таком вот виде:
string current_date = DateTime.Now.ToString("dd.MM");
C#
1
2
3
4
for (i = 1; i <= worksheet.UsedRange.Rows.Count; i++)
{
     if (worksheet.Cells[4][i].Value.ToString("dd.MM").Equals(current_date))
}
Если я правильно понимаю ситуацию то это должно дать правильный результат.
0
12.11.2012, 10:11
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.11.2012, 10:11

как сравнить даты ?
допустим есть переменные (даты): a = &quot;08/12/2005&quot; b = &quot;08/12/2008&quot; как...

Занести в базу значение текущей даты и времени: Ошибка Incorrect syntax near
Здравствуйте! Хочу занести в базу значение текущей даты и время. Тип в базе...

На основе введенной даты рождения и текущей даты сообщить пользователю, сколько он прожил дней
3. Написать программу, которая на основе введенной даты рождения и текущей даты...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru