AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: База знаний и проекты
All
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны Забыли пароль?

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 09.06.2008, 18:36   #21  
IvanOFF is offline
IvanOFF
MCTS
MCBMSS
 
60 / 75 (3) ++++
Регистрация: 22.09.2005
Адрес: Москва
Цитата:
Сообщение от Gustav Посмотреть сообщение
В Excel нет отдельного типа "Время" (не путать с форматом, отображающим только время, без даты). Есть единый тип "Дата", в котором собственно дата является целым числом (до запятой), а время дробным (после запятой). Особенно хорошо это видно при программировании на VBA: есть тип Date, но нет Time.

Чтобы загрузить время в Аксапту следует до импорта из Excel в самом Excel:
- либо превратить время в вещественный тип путем назначения столбцу формата General (Общий);
- либо превратить его в вещественный тип, умножить на 86400 и тащить в Аксапту в виде общего количества секунд;
- либо распарсить исходное время на часы, минуты и секунды, импортировать эти 3 значения по отдельности и уже в Аксапте собирать,
- либо превратить в текст вида "09:30:00" при помощи функции вроде =ТЕКСТ(A1,"[ЧЧ]:ММ:СС").
Спасибо! Теперь все понятно!
Старый 02.10.2008, 17:52   #22  
Stainless is offline
Stainless
Участник
MCBMSS
Columbus IT
 
34 / 73 (3) ++++
Регистрация: 26.01.2007
Как перейти к конкретной записи recordset?
Почитал help на эту тему, там есть метод move, но заставить его работать у меня не получилось.

Ответ нашелся очень просто:
X++:
recordset.move( NumRecords, Start );
более подробно: http://www.devguru.com/Technologies/...dset_move.html

Последний раз редактировалось Stainless; 02.10.2008 в 18:05.
Старый 02.10.2008, 19:02   #23  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
Лучший по профессии 2009
SAP
 
1,845 / 1143 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
хм, в хелпе тоже самое, вроде:
Цитата:
Сообщение от файл ADO210.CHM
Move Method

Moves the position of the current record in a Recordset object.

Syntax

recordset.Move NumRecords, Start
Или отсутствие скобок смутило? В хелпе синтаксис для Visual Basic приводится.
Старый 07.11.2008, 13:21   #24  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
Лучший по профессии 2009
SAP
 
1,845 / 1143 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
? э-хе-хе...
Испытываю возобновление интереса к теме и вот в связи с чем. ADODB.Recordset имеет полезнейшие свойства Filter и Sort, которыми можно эффективно пользоваться, фильтруя исходный набор или изменяя порядок записей исходного Recordset'а и далее перебирая в цикле нужные записи в нужном порядке.

Резонно было бы предположить, хотя про это нигде не сказано в справке, что методом CopyFromRecordset должен выгружаться набор записей с учетом фильтрации и сортировки. Увы, при управлении Excel из Аксапты этого не происходит:

X++:
static void Job103(Args _args)
{
    #CCADO

    ComExcelDocument_RU doc = new ComExcelDocument_RU();
    COM                 rst = new COM('ADODB.Recordset');

    COM     xlApp;
    COM     wbook;
    COM     activeSheet;
    COM     range;
    COM     flds,fld;

    int     i;
    ;

    doc.NewFile('',false);
    wbook = doc.getComDocument();

    xlApp = wbook.Parent();
    activeSheet = xlApp.ActiveSheet();

    flds = rst.Fields();

    flds.Append('myField1', #adVarChar, 50);
    flds.Append('myField2', #adInteger);
    
    rst.Open();

    for (i=1;i<=1000;i++)
    {
        rst.AddNew();
            fld = flds.Item(0); fld.Value(int2str(i));
            fld = flds.Item(1); fld.Value(i*2);
        rst.Update();
    }

    rst.Filter("myField1 Like '*24*'");
    rst.Sort('myField1 DESC');

    rst.MoveFirst();

    range = activeSheet.Range('A1');
    range.CopyFromRecordset(rst, 300);

    range = activeSheet.Range('A1000');
    range.CopyFromRecordset(rst, 300);

    doc.visible(true);

    
    // чтобы показать, что набор действительно фильтруется и сортируется
    rst.MoveFirst();
    while (! rst.EOF())
    {
        info(strFmt('%1 --- %2', 
                    new CCADOField( flds.Item(0) ).value(),
                    new CCADOField( flds.Item(1) ).value()));
        rst.MoveNext();
    }
}
Поведение метода CopyFromRecordset в этом примере не соответствует ожиданиям. Он не учитывает не только сортировку и фильтрацию, но и декларированное в справке продвижение указателя текущей записи. Так, по здравой логике, первый оператор "range.CopyFromRecordset(rst, 300);" должен вывести в Excel первые 300 записей и установить указатель на 301-ю. Второй же оператор "range.CopyFromRecordset(rst, 300);" должен вывести следующие 300 записей: с 301-й по 600-ю и остановиться на 601-й.

Но этого не происходит. Вместо этого - и начиная с ячейки A1, и начиная с ячейки A1000 - одинаково выводятся первые 300 записей исходного набора. А хотелось бы, чтобы вывелись только 20 записей с ячейки A1, т.е. те записи, которые пример выводит в окно Infolog.

Возможно мои претензии необоснованы и CopyFromRecordset должен себя вести именно так, как ведет себя в этом примере? Я уже было засомневался, вернее, почти отказался от своих "претензий", но решился на еще одну проверку - в самом Excel на VBA:
Код:
 
Sub Job103_VBA()

    Dim i As Integer
    
    Dim rst As Object
    Dim flds As Object
    
    Dim xlApp As Excel.Application

    Set rst = CreateObject("ADODB.Recordset")
    'я сознательно создал rst через CreateObject, а не как New ADODB.Recordset, 
    'чтобы не искать ссылку на ADO через Tools\References    
    
    Set flds = rst.Fields
    
    flds.Append "myField1", 200, 50 '200 = adVarChar
    flds.Append "myField2", 3 '3 = adInteger
    
    rst.Open
    
    For i = 1 To 1000
        rst.AddNew
            rst.Fields(0).Value = i
            rst.Fields(1).Value = i * 2
        rst.Update
    Next i
    
    rst.Filter = "myField1 Like '*24*'"
    rst.Sort = "myField1 DESC"
    
    rst.MoveFirst
    
    'Set xlApp = New Excel.Application
    Set xlApp = Application
    
    xlApp.Workbooks.Add
      
    xlApp.Range("A1").CopyFromRecordset rst, 300
    xlApp.Range("A1000").CopyFromRecordset rst, 300
    
    xlApp.Visible = True
    
End Sub
Что скажете о результате? Он такой, как хотелось! Ура? Увы, нет. Закомментируйте строку "Set xlApp = Application" и раскомментируйте строку выше, т.е. должно стать вот так:
Код:
 
    Set xlApp = New Excel.Application
    'Set xlApp = Application
Таким образом, теперь мы из Excel создаем другой Excel и выводим рекордсет в этот другой. Результат такой же, как при выводе из Аксапты - не такой, как хочется.

Есть ли у кого какие-нибудь соображения? Может, кто-нибудь интересующийся продвинуто заглянет какими-нибудь крутыми вьюерами в тайны происходящих процессов COM-автоматизации? Может быть удастся победить ситуацию использованием каких-нибудь COMDispFunction?


P.S. Проделал даже такой финт. Создал шаблон xlt, в который зашил VBA-процедуру:
Код:
 
Sub myCopyFromRecordset(ByVal rng As Range, ByVal rst As ADODB.Recordset, ByVal maxRows As Integer)
    rng.CopyFromRecordset rst, maxRows
End Sub
Из Аксапты создал новый файл на базе этого шаблона и вызвал процедуру строкой:
X++:
    xlApp.Run('myCopyFromRecordset', range, rst, 300);
Результат - тоже не тот
Старый 07.11.2008, 20:12   #25  
sukhanchik is offline
sukhanchik
Moderator
Аватар для sukhanchik
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
MCBMSS
Злыдни
 
2,417 / 1463 (53) ++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от Gustav Посмотреть сообщение
Резонно было бы предположить, хотя про это нигде не сказано в справке, что методом CopyFromRecordset должен выгружаться набор записей с учетом фильтрации и сортировки.
Для тех, кто программировал в Access еще в DAO (а в общем-то DAO можно считать прародителем ADO) такое предположение отнюдь не резонно. Методы Filter и Sort действовали ПОСЛЕ выборки, а метод CopyFromRecordset копировал именно все записи выборки (он совершенно не собирался смотреть на методы Filter и Sort). Именно поэтому в Access приветствовалось программирование через SQL-запросы, а не через методы работы с таблицами.

Я удивлен другим. Я удивлен - что CopyFromRecordset все-таки может копировать с учетом фильтрации - но об этом видимо "помнит" только текущее приложение - т.е. поддержка реализована не на уровне "ядра" ADO
__________________
Возможно сделать все. Вопрос времени
Старый 23.04.2009, 11:32   #26  
sta[z] is offline
sta[z]
Участник
 
29 / 11 (1) +
Регистрация: 13.10.2005
Адрес: г. Москва
Возникла проблема с экспортом через ADO в Excel полей с типом дата. Если переносить как adbSTR, то это не устраивает конечных пользователей (не работает нормльно фильтрация). Если переносить как adDBDate, то datenull() отображается в Excel как 02.01.1900. Применение формата "ДД.ММ.ГГГГ" к ячейке не помогает. Можно ли как-нибудь передать дату так, чтобы пустая дата не отображалась?
Старый 23.04.2009, 11:40   #27  
sta[z] is offline
sta[z]
Участник
 
29 / 11 (1) +
Регистрация: 13.10.2005
Адрес: г. Москва
Сам нашел выход. Если значение поля в Axapte datenull(), то нужно писать в ADO field.value() не значение поля, а просто 0. А в Excel у активного листа выставить в false параметр DisplayZeros(0).
Старый 23.04.2009, 11:44   #28  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,432 / 309 (13) ++++++
Регистрация: 23.03.2006
Цитата:
Сообщение от sta[z] Посмотреть сообщение
Сам нашел выход. Если значение поля в Axapte datenull(), то нужно писать в ADO field.value() не значение поля, а просто 0. А в Excel у активного листа выставить в false параметр DisplayZeros(0).
а если просто не заполнять поле в таких случаях?
За это сообщение автора поблагодарили: Gustav (2).
Старый 23.04.2009, 12:06   #29  
sta[z] is offline
sta[z]
Участник
 
29 / 11 (1) +
Регистрация: 13.10.2005
Адрес: г. Москва
Тот же результат, что и с 0.
Старый 23.04.2009, 13:58   #30  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
Лучший по профессии 2009
SAP
 
1,845 / 1143 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Цитата:
Сообщение от ice Посмотреть сообщение
а если просто не заполнять поле в таких случаях?
Да, именно так и надо делать. Лично я - сторонник этого способа
Цитата:
Сообщение от sta[z] Посмотреть сообщение
Тот же результат, что и с 0.
У меня так происходит, если тип поля рекордсета задавать константой adDate(7). А если взять adDBDate, которая 133, то на месте нулевых дат в Excel будут желаемые пустые ячейки. Во всяком случае для сочетания Ax 3.0 SP4 + Oracle 10 + Excel 2003 это так.
Старый 23.04.2009, 17:29   #31  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
Лучший по профессии 2009
SAP
 
1,845 / 1143 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Пользуясь сегодняшнем случаем наконец-то подправил в своем рабочем классе (практически в персональном "пролетариате") метод, устанавливающий значение в поле рекордсета:
X++:
#CCADO
void setValue(anytype _fldName, anytype _fldValue)
{
    // _fldName - можно текстовое имя, а можно числовое, начиная с 1 (!), а не 0 как в самом ADO
    anytype fldName;
    ;
    if (typeof(_fldName)==Types::Integer)
        fldName = _fldName - 1;
    else
        fldName = _fldName;     

    fld = flds.Item(fldName); // COM flds и fld - полЯ и полЕ рекордсета, определены в Class Declaration

    if (! ((fld.Type()==#adDate || fld.Type()==#adDBDate) && !_fldValue) )
    {
        fld.Value(_fldValue); // если непустая дата или любое др.значение
    }
    // иначе если значение - пустая дата, то вообще не прописываем в поле
}
И теперь можно не обращать внимание на дату. А раньше приходилось делать проверку в самом цикле вывода:
X++:
if (ltDb.TransDate)
    out2xls.setValue(nextNum(),ltDb.TransDate);
Способ с проверкой в цикле, конечно, побыстрее будет, но вряд ли этот временнОй выигрыш так уж критичен, а по сему упрятывание обработки пустой даты в метод setValue выглядит комфортнее.
Старый 29.04.2009, 13:16   #32  
online
gl00mie
Участник
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
MCBMSS
Most Valuable Professional
 
3,425 / 4225 (147) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
А я во вспомогательном канале вывода в Excel зашел с другого конца: при создании структуры ADO.Recordset я указываю опциональный признак того, надо ли в соотв. колонке избавиться от "незначащих" значений, и после вывода просто делают замену средствами самого Excel таких значений на то, что возвращает COMVariant::createNoValue()
X++:
// очистка ячеек с "пустыми" значениями (ноль для чисел либо 01.01.1900 для дат), чтоб не надо было докручивать шаблон для их сокрытия
// _cell - ячейка, на которой в outputReportBody() вызывается метод CopyFromRecordset()
protected void clearEmptyCells(COM _cell)
{
    COMVariant  cvSrcValue;
    COMVariant  cvDstValue;
    str         strAddr;
    container   conFieldInfo;
    boolean     bClearEmpty;
    Counter     cnRows;
    Counter     n;
    COM         oRng;                                           // область, в которой будет производиться замена
    ;
    cnRows      = rstAxa.RecordCount();                         // количество выведенных строк данных
    cvDstValue  = COMVariant::createNoValue();                  // создаем пустое значение
    for (n = 1; n <= arrFields.lastIndex(); n++)
    {
        conFieldInfo = arrFields.value( n );
        if (conlen(conFieldInfo) >= #ConPosFieldInfoClearEmpty) // по умолчанию этого поля в контейнеере быть не должно
        {
            bClearEmpty = conpeek( conFieldInfo, #ConPosFieldInfoClearEmpty );
            if (!bClearEmpty)
                continue;
            cvSrcValue  = this.getEmptyVariantValue( conpeek( conFieldInfo, #ConPosFieldInfoType ) );
            if (!cvSrcValue)                                    // если вернулся null, значит, тип не поддерживается
                continue;
            // формируем адрес диапазона ячеек *относительно* _cell
            strAddr = ComExceldocument_RU::numToNameCell( n, 1 );
            if (cnRows > 1)
                strAddr += @':' + ComExceldocument_RU::numToNameCell( n, cnRows );
            oRng = _cell.range( strAddr );                      // получаем столбец внутри диапазона _cell
            oRng.Replace( cvSrcValue, cvDstValue, #xlWhole, #xlByColumns );
        }
    }
}
// возвращает COMVariant, представляющий "пустое" значение для указанного типа ADO, либо null, если указанный тип не поддерживается
protected COMVariant getEmptyVariantValue( Integer _adoType )
{
    COMVariant  ret;
    ;
    switch( _adoType )
    {
        case #adDate :
        case #adDBDate :
        case #adDBTimeStamp :
            ret = COMVariant::createFromDateAndTime( datenull(), 0 );
            break;
        case #adSingle :
        case #adDouble :
        case #adCurrency :
        case #adDecimal :
        case #adNumeric :
            ret = COMVariant::createFromReal( 0.0 );
            break;
        case #adTinyInt :
        case #adSmallInt :
        case #adInteger :
        case #adBigInt :
        case #adUnsignedTinyInt :
        case #adUnsignedSmallInt :
        case #adUnsignedInt :
        case #adUnsignedBigInt :
            ret = COMVariant::createFromInt( 0 );
            break;
        default :
            ret = null;
            break;
    }
    return ret;
}
Хотя, конечно, просто не устанавливать значение ячейки в Recordset, пожалуй, как-то "прямее"
PS. По ходу реализации наткнулся на одни "грабли": оказалось, что COMVariant::createFromDate( datenull() ) возвращает COMVariant не со значением 01.01.1900 00:00, как можно было бы ожидать, а со значением 01.01.1900 <текущее_время>!
Старый 29.04.2009, 15:17   #33  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
Лучший по профессии 2009
SAP
 
1,845 / 1143 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Цитата:
Сообщение от gl00mie Посмотреть сообщение
PS. По ходу реализации наткнулся на одни "грабли": оказалось, что COMVariant::createFromDate( datenull() ) возвращает COMVariant не со значением 01.01.1900 00:00, как можно было бы ожидать, а со значением 01.01.1900 <текущее_время>!
Аналогичные грабли наблюдаются при выводе, если тип поля даты рекордсета задать #adDate (7). Причем, текущее время добавляется хвостом к нормальным ненулевым датам! А вот dateNull() выводится без "хвоста" в виде 0 (!) января 1900 года (00.01.1900).

Вот почему мы любим тип #adDBDate (133), который, как положено, сохраняет только дату без времени
За это сообщение автора поблагодарили: alex55 (1).
Старый 06.05.2010, 10:00   #34  
Roman N. Krivov is offline
Roman N. Krivov
Участник
 
25 / 11 (1) +
Регистрация: 04.05.2010
Адрес: Мир, Россия, Московская область
Как передать в Excel (через ADO) число типа real так, чтобы оно не преобразовывалось в дату? Я указывают тип поля adDouble, а Excel всё равно преобразует в дату.
Старый 06.05.2010, 10:29   #35  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2014
 
3,048 / 1489 (56) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Roman N. Krivov Посмотреть сообщение
Я указывают тип поля adDouble, а Excel всё равно преобразует в дату.
Не воспроизвелось
X++:
static void Job20100506(Args _args)
{
    #define.adDouble(5)
    COM Recordset;
    COM Fields;
    COM Field;
    COM Application;
    COM Workbooks;
    COM Workbook;
    COM Worksheets;
    COM Worksheet;
    COM Range;
    ;
    
    Recordset = new COM('ADODB.Recordset');
    Fields = Recordset.Fields();
    Fields.Append('Field1', #adDouble);
    
    Recordset.Open();
    Recordset.AddNew();
    Field = Fields.Item('Field1');
    Field.Value(123.45);
    Recordset.Update();
 
    Application = new COM('Excel.Application');
    Workbooks = Application.Workbooks();
    Workbook = Workbooks.add();
    Worksheets = Workbook.Worksheets();
    Worksheet  = Worksheets.Item(1);
    Range  = Worksheet.Range('A1');
    
    Range.CopyFromRecordset(Recordset);

    Recordset.Close();
    Application.Visible(true);
}
Старый 06.05.2010, 10:35   #36  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
Лучший по профессии 2009
SAP
 
1,845 / 1143 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Тоже не воспроизвелось
X++:
static void Job298(Args _args)
{
    #CCADO

    COM rng  = SysExcelApplication::construct().workbooks().add().worksheets().itemFromNum(1).range('A1').comObject();
    COM rst  = new COM('ADODB.Recordset');
    COM flds = rst.Fields();
    COM fld;
    int i;

    flds.Append('MyReal', #adDouble);
    rst.Open();

    fld = flds.Item('MyReal');

    for (i=1; i<=10; i++)
    {
        rst.AddNew();
            fld.Value(100 + i/10);
        rst.Update();
    }
    rng.CopyFromRecordset(rst);
    COM::createFromObject(rng.Application()).Visible(true); // отобразим Excel
}
На чистом листе Excel не воспроизводится. Где-то у вас форматирование всё же выполняется, наверное...
Старый 06.05.2010, 10:51   #37  
Roman N. Krivov is offline
Roman N. Krivov
Участник
 
25 / 11 (1) +
Регистрация: 04.05.2010
Адрес: Мир, Россия, Московская область
Цитата:
Сообщение от Gustav Посмотреть сообщение
На чистом листе Excel не воспроизводится. Где-то у вас форматирование всё же выполняется, наверное...
Точно не воспроизводится.
А меня в шаблоне в ячейке указан формат "Число". И если передавать как строку - всё работает. Но уже второй день бьюсь над этим. Пришлось передавать поля типа "Строка"
Старый 06.05.2010, 11:11   #38  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
Лучший по профессии 2009
SAP
 
1,845 / 1143 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Я обычно adDouble не использую, а использую для adCurrency.
Конечно, на файл шаблона бы взглянуть... Хотя бы на тот его фрагмент, куда пишется adDouble.
Можно выложить?
Старый 06.05.2010, 13:01   #39  
Roman N. Krivov is offline
Roman N. Krivov
Участник
 
25 / 11 (1) +
Регистрация: 04.05.2010
Адрес: Мир, Россия, Московская область
Цитата:
Сообщение от Gustav Посмотреть сообщение
Я обычно adDouble не использую, а использую для adCurrency.
Конечно, на файл шаблона бы взглянуть... Хотя бы на тот его фрагмент, куда пишется adDouble.
Можно выложить?
Выложил результат работы и шаблон
Изображения
 
Вложения
Тип файла: zip Act.zip (5.2 Кб, 20 просмотров)

Последний раз редактировалось Roman N. Krivov; 06.05.2010 в 13:05.
Старый 06.05.2010, 14:07   #40  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
Лучший по профессии 2009
SAP
 
1,845 / 1143 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Роман, у меня два вопроса:
  1. Рекордсет создаете с учетом всех колонок, попадающих в область бланка? Т.е. у вас должно быть много фиктивных и немного содержательных - т.е. получается 16 содержательных где-то из 85 всего.
  2. Как вставляете новые строки? Сразу всё необходимое кол-во перед исходной 19-й строкой? Потом дополнительно еще формат этой исходной распространяете на добавленные?
Теги
ado, comvariant, excel, faq, odbc, sql, интеграция, прямой доступ, формат дат, экспорт, экспорт в excel

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Вспомогательный класс для импорта из Excel через ADO gl00mie DAX: База знаний и проекты 75 16.04.2014 11:47
gl00mie: Read Excel table via ADO Blog bot DAX Blogs 2 09.04.2010 08:32
C# and AX Development: Using ADO for interfacing AX with an external database Blog bot DAX Blogs 0 05.08.2008 05:18
casperkamal: Using ADO to read from Excel in Microsoft Dynamics Ax Blog bot DAX Blogs 2 14.05.2007 11:59
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 17:00.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.