Главная страница

современный фортран , Бортеньев. О. В. Бартеньев Современный Фортран


Скачать 2.24 Mb.
НазваниеО. В. Бартеньев Современный Фортран
Анкорсовременный фортран , Бортеньев.pdf
Дата28.05.2018
Размер2.24 Mb.
Формат файлаpdf
Имя файласовременный фортран , Бортеньев.pdf
ТипДокументы
#19729
страница44 из 49
1   ...   41   42   43   44   45   46   47   48   49
399

О. В. Бартеньев. Современный ФОРТРАН
integer(2), dimension(:), intent(out) :: unicodestr integer(4), intent(in), optional :: flags end function MBConvertMBToUnicode integer(4) function MBConvertUnicodeToMB(unicodestr, mbstr, flags)
!dec$ attributes default :: MBConvertUnicodeToMB integer(2), dimension(:), intent(in) :: unicodestr character(*), intent(out) :: mbstr integer(4), optional, intent(in) :: flags end function MBConvertUnicodeToMB end interface contains
! Процедуры преобразования строки Фортрана в строку BSTR и обратно;
! заимствованы из файла dfcom.f90 integer(4) function ConvertStringToBSTR(string) character(*), intent(in) :: string integer(4) bstr, length integer(2), allocatable :: unistr(:)
! Строке UNICODE
! Первый вызов MBConvertMBToUnicode определяет длину строки string allocate(unistr(0)) length = MBConvertMBToUnicode(string, unistr) deallocate(unistr) if(length < 0) then
! Специальный случай всех пробелов allocate(unistr(2)) unistr(1) = #20
! Один пробел unistr(2) = 0
! Нуль-символ else
! Второй вызов MBConvertMBToUnicode выполняет преобразование allocate(unistr(length + 1)) length = MBConvertMBToUnicode(string, unistr) unistr(length + 1) = 0
! Завершаем строку нуль-символом end if bstr = SysAllocString(unistr) ! Размещаем BSTR-строку deallocate(unistr)
ConvertStringToBSTR = bstr ! Возвращаем результат end function ConvertStringToBSTR integer(4) function ConvertBSTRToString(bstr, string) integer(4), intent(in) :: bstr character(*), intent(out) :: string integer(4) length length = SysStringLen(bstr)
ConvertBSTRToString = Convert(bstr, length, string) contains integer(4) function Convert(bstr, length, string) integer(4), intent(in) :: bstr, length character(*), intent(out) :: string integer(2) :: unistr(length)
400

12. Конструктор модулей для объектов ActiveX pointer(p, unistr) p = bstr
Convert = MBConvertUnicodeToMB(unistr, string) end function Convert end function ConvertBSTRToString end module mycom module adobjs implicit none
! Указатели на объекты integer(4) :: excelapp, workbooks, workbook, worksheets, worksheet, range, charts, chart integer(4) :: cells(12) integer(4) :: categoryAxis, valueAxis integer(4) :: bstr1, bstr2, bstr3 contains subroutine initobjects( )
! Задает начальные значения переменных integer(4) i excelapp = 0; workbooks = 0; workbook = 0; worksheets = 0; worksheet = 0 range = 0; charts = 0; chart = 0; categoryAxis = 0; valueAxis = 0; cells = 0 bstr1 = 0; bstr2 = 0; bstr3 = 0 end subroutine initobjects subroutine releaseobjects( )
! Освобождает созданные объекты use mycom
! Вместо use dfcom integer(4) status, i if(range /= 0) status = COMReleaseObject(range) if(chart /= 0) status = COMReleaseObject(chart) if(charts /= 0) status = COMReleaseObject(charts) if(worksheets /= 0) status = COMReleaseObject(worksheet) if(worksheet /= 0) status = COMReleaseObject(worksheet) if(workbook /= 0) status = COMReleaseObject(workbook) if(workbooks /= 0) status = COMReleaseObject(workbooks) do i =1, 12 if(cells(i) /= 0) status = COMReleaseObject(cells(i)) end do if(categoryAxis /= 0) status = COMReleaseObject(categoryAxis) if(valueAxis /= 0) status = COMReleaseObject(valueAxis) if(excelapp /= 0) status = COMReleaseObject(excelapp) if(bstr1 /= 0) call SysFreeString(bstr1) if(bstr2 /= 0) call SysFreeString(bstr2) if(bstr3 /= 0) call SysFreeString(bstr3) end subroutine releaseobjects end module adobjs program ExcelSample
! Взамен ссылок на модули DFCOM, DFCOMTY и EXCEL97B use mycom use adobjs use excel97b
401

О. В. Бартеньев. Современный ФОРТРАН
implicit none integer(4) status, loopCount, roll, maxScale, i, die(2) character(32) :: fname real(4) rnd(2) integer(2) :: cellCounts(12)
! Массив, отображаемый в виде диаграммы type(variant) :: vbstr1, vbstr2, vbstr3, vint print *, 'Enter Excel file name' read *, fname call initobjects( )
! Инициализация объектов cellCounts = 0
! Инициализация массива call COMInitialize(status)
! Инициализируем COM и создаем объект Excel call COMCreateObject("Excel.Application.8", excelapp, status) if(excelapp == 0) stop 'Unable to create Excel object; Aborting' call $Application_SetVisible(excelapp, .true.)
! Последовательность операций:
! получить указатель на объект "Рабочая книга";
! открыть файл fname и создать экземпляр объекта "Рабочая книга";
! получить указатель на объект "Рабочий лист";
! задать диапазон заполняемых ячеек таблицы;
! заполнить ячейки из выбранного диапазона значениями массива cellCounts;
! задать отображаемый на диаграмме диапазон ячеек таблицы;
! получить указатель на объект "Диаграмма" и сформировать этот объект;
! задать параметры диаграммы и вызвать построитель диаграмм;
! задать параметры осей диаграммы;
! задать максимальную координату на оси значений
! сформировать отображаемый массив cellCounts;
! Передать данные в Excel и отобразить их на диаграмме
! Псевдокод:
! workbooks = excelapp.GetWorkbooks( )
! workbook = workbooks.Open(spreadsheet)
! worksheet = workbook.GetActiveSheet
! range = worksheet.GetRange("A1", "L1")
! range.Select( )
! charts = workbook.GetCharts( )
! chart = charts.Add( )
402

12. Конструктор модулей для объектов ActiveX
! chart.ChartWizard(gallery=chartType, title=title, categoryTitle=title, valueTitle=title)
! valueAxis = chart.Axes(type = xlValue, axisGroup = xlPrimary)
! valueAxis.MaximumScale(loopcount / 5)
! Аналогичный код на Фортране:
! Получаем указатель на объект-набор"Рабочая книга" - workbooks workbooks = $Application_GetWorkbooks(excelapp, $status = status) call Check_Status(status, "Unable to get workbooks object")
! Создаем workbook - экземпляр объекта workbooks
! Открываем заданный файл. Указываем в качестве параметра имя XLS-файла workbook = Workbooks_Open(workbooks, fname, $status = status) call Check_Status(status, "Unable to get Workbook object; see if the file path is correct")
! Получаем worksheet - указатель на объект "Рабочий лист" worksheet = $Workbook_GetActiveSheet(workbook, status) call Check_Status(status, "Unable to get Worksheet object") call VariantInit(vbstr1)
! Создаем новую диаграмму call VariantInit(vbstr2) vbstr1%vt = vt_bstr; bstr1 = ConvertStringToBSTR("A1"); vbstr1%vu%ptr_val = bstr1 vbstr2%vt = vt_bstr; bstr2 = ConvertStringToBSTR("L1"); vbstr2%vu%ptr_val = bstr2
! Задаем диапазон заполняемых ячеек таблицы Excel - от A1 до L1 range = $Worksheet_GetRange(worksheet, vbstr1, vbstr2, status) call Check_Status(status, "Unable to get range object") status = VariantClear(vbstr1); bstr1 = 0 status = VariantClear(vbstr2); bstr2 = 0
! Заполняем ячейки из выбранного диапазона значениями массива cellCounts status = AUTOSetProperty(range, "Value", cellCounts)
! Выбираем отображаемый на диаграмме диапазон ячеек call Range_Select(range, status)
! Получаем указатель на объект "Диаграмма" charts = $Workbook_GetCharts(workbook, $status = status) call Check_Status(status, " Unable to get charts object") chart = Charts_Add(charts, $status = status) call Check_Status(status, " Unable to add chart object")
! Вызываем построитель диаграмм. Псевдокод:
! chart.ChartWizard(gallery=chartType, title=title, categoryTitle=title, valueTitle=title) call VariantInit(vint)
! Код Фортрана
! Вид гистограммы - объемные вертикальные столбцы vint%vt = vt_i4; vint%vu%long_val = 11 call VariantInit(vbstr1)
! Инициализация варианта vbstr1%vt = vt_bstr
! Тип хранимого значения
403

О. В. Бартеньев. Современный ФОРТРАН
bstr1 = ConvertStringToBSTR("Гистограмма cellCounts"); vbstr1%vu%ptr_val = bstr1 call VariantInit(vbstr2); vbstr2%vt = vt_bstr bstr2 = ConvertStringToBSTR("Столбец"); vbstr2%vu%ptr_val = bstr2 call VariantInit(vbstr3); vbstr3%vt = vt_bstr bstr3 = ConvertStringToBSTR("Значение"); vbstr3%vu%ptr_val = bstr3 call $Chart_ChartWizard(chart,
&
Gallery = vint,
&
! Вид диаграммы
Title = vbstr1,
&
! Заголовок диаграммы
CategoryTitle = vbstr2,
&
! Заголовок горизонтальной оси
ValueTitle = vbstr3,
&
! Заголовок вертикальной оси
$status = status) call Check_Status(status, "Unable to invoke ChartWizard") status = VariantClear(vbstr1); bstr1 = 0
! Очищаем варианты status = VariantClear(vbstr2); bstr2 = 0 status = VariantClear(vbstr3); bstr3 = 0 call VariantInit(vint)
! Устанавливаем свойства осей диаграммы vint%vt = vt_i4; vint%vu%long_val = xlValue valueAxis = $Chart_Axes(chart, vint, xlPrimary, $status = status) call Check_Status(status, "Unable to get axis object") loopcount = 1000
! Число вызовов датчика случайных чисел maxScale = loopcount / 5
! Максимальная величина на оси значений status = AUTOSetProperty(valueAxis, "MaximumScale", maxScale) call Check_Status(status, "Unable to set axis MaximumScale") call random_seed( )
! Затравка датчика случайных чисел do i = 1, loopcount
! Формируем отображаемый массив call random_number(rnd)
! Генерируем два случайных числа die = nint((rnd * 6) + 0.5) roll = sum(die) cellCounts(roll) = cellCounts(roll) + 1 end do
! Отображаем данные массива cellCounts в таблице Excel и на диаграмме status = AUTOSetProperty(range, "Value", cellCounts) call Check_Status(status, "Unable to set range value") call releaseobjects( )
! Освобождаем объекты call COMUninitialize( ) end program ExcelSample subroutine Check_Status(olestatus, errorMsg) use adobjs integer(4) :: olestatus character(*) :: errorMsg if(olestatus >= 0) return call releaseobjects( )
! Освобождаем объекты write(*, '(a, "; OLE error status = 0x", z8.8, "; Aborting")') trim(errorMsg), olestatus stop end subroutine Check_Status
! Результат приведен на рис. 12.6
404

12. Конструктор модулей для объектов ActiveX
Рис. 12.6. Отображение массива cellCounts на диаграмме Excel
Замечания:
1. Если после запуска приложения были сохранены изменения в файле histo.xls, то его нужно будет восстановить в исходном виде, например списав с CD, содержащем поставку CVF.
2. Все вызываемые из программы ExcelSample процедуры инициализации и задания свойств объектов сосредоточены в модуле EXCEL97B, который сформирован из полученного при помощи КМ модуля EXEL97A. module excel97b use mycomty use mycom implicit none
! Объявления констант взяты из файла excel97a.f90 type(guid), parameter :: CLSID_Global =
& guid(#00020812, #0000, #0000,
& char('c0'x)//char('00'x)//char('00'x)//char('00'x)//
& char('00'x)//char('00'x)//char('00'x)//char('46'x)) type(guid), parameter :: CLSID_Worksheet =
& guid(#00020820, #0000, #0000,
& char('c0'x)//char('00'x)//char('00'x)//char('00'x)//
& char('00'x)//char('00'x)//char('00'x)//char('46'x)) type(guid), parameter :: CLSID_Chart =
& guid(#00020821, #0000, #0000,
&
405

О. В. Бартеньев. Современный ФОРТРАН
char('c0'x)//char('00'x)//char('00'x)//char('00'x)//
& char('00'x)//char('00'x)//char('00'x)//char('46'x)) type(guid), parameter :: CLSID_Application =
& guid(#00024500, #0000, #0000,
& char('c0'x)//char('00'x)//char('00'x)//char('00'x)//
& char('00'x)//char('00'x)//char('00'x)//char('46'x))
! XlAxisGroup integer, parameter :: xlPrimary = 1, xlSecondary = 2
! XlAxisType integer, parameter :: xlCategory = 1, xlSeriesAxis = 3, xlValue = 2 contains
! Модульные процедуры
! Все процедуры взяты из файла excel97a.f90 subroutine $Application_SetVisible($object, $arg1, $status)
!dec$ attributes dllexport :: $Application_SetVisible
!dec$ attributes value :: $object
!dec$ attributes reference :: $arg1
!dec$ attributes reference :: $status implicit none integer(4), intent(in) :: $object
! Указатель на объект logical(2), intent(in) :: $arg1 integer(4), intent(out), optional :: $status
! Статус метода integer(4) $$status, invokeargs invokeargs = AUTOAllocateInvokeArgs( ) call AUTOAddArg(invokeargs, 'Visible', $arg1)
$$status = AUTOSetPropertyByID($object, 558, invokeargs) if(present($status)) $status = $$status call AUTODeallocateInvokeArgs(invokeargs) end subroutine $Application_SetVisible
! $Application_GetWorkbooks возвращает значение типа POINTER(p, INTEGER(4)) integer(4) function $Application_GetWorkbooks($object, $status)
!dec$ attributes dllexport :: $Application_GetWorkbooks
!dec$ attributes value :: $object
!dec$ attributes reference :: $status implicit none integer(4), intent(in) :: $object
! Указатель на объект integer(4), intent(out), optional :: $status
! Статус метода integer(4) $$status, invokeargs integer(4), volatile :: $return invokeargs = AUTOAllocateInvokeArgs( ) call AUTOAddArg(invokeargs, 'Workbooks', $return, .true., vt_dispatch)
$$status = AUTOGetPropertyByID($object, 572, invokeargs) if(present($status)) $status = $$status
$Application_GetWorkbooks = $return call AUTODeallocateInvokeArgs(invokeargs) end function $Application_GetWorkbooks
406

12. Конструктор модулей для объектов ActiveX
! Workbooks_Open возвращает значение типа POINTER(p, INTEGER(4)) integer(4) function Workbooks_Open($object, Filename, UpdateLinks, ReadOnly,
&
Format, Password, WriteResPassword, IgnoreReadOnlyRecommended,
&
Origin, Delimiter, Editable, Notify, Converter, AddToMru, $status)
!dec$ attributes dllexport :: Workbooks_Open
!dec$ attributes value :: $object
!dec$ attributes reference :: Filename
!dec$ attributes reference :: UpdateLinks
!dec$ attributes reference :: ReadOnly
!dec$ attributes reference :: Format
!dec$ attributes reference :: Password
!dec$ attributes reference :: WriteResPassword
!dec$ attributes reference :: IgnoreReadOnlyRecommended
!dec$ attributes reference :: Origin
!dec$ attributes reference :: Delimiter
!dec$ attributes reference :: Editable
!dec$ attributes reference :: Notify
!dec$ attributes reference :: Converter
!dec$ attributes reference :: AddToMru
!dec$ attributes reference :: $status implicit none integer(4), intent(in) :: $object
! Указатель на объект character(*), intent(in) :: Filename
! Имя XLS-файла type(variant), intent(in), optional :: UpdateLinks, ReadOnly, Format, Password,
&
WriteResPassword, IgnoreReadOnlyRecommended, Origin, Delimiter,
&
Editable, Notify, Converter, AddToMru integer(4), intent(out), optional :: $status
! Статус метода integer(4) $$status, invokeargs integer(4), volatile :: $return invokeargs = AUTOAllocateInvokeArgs( )
! Константы '$RETURN', '$ARGnn' записываются прописными буквами call AUTOAddArg(invokeargs, '$RETURN', $return, .true., vt_dispatch) call AUTOAddArg(invokeargs, '$ARG1', Filename, .false., vt_bstr) if(present(UpdateLinks)) call AUTOAddArg(invokeargs, '$ARG2',
&
UpdateLinks, .false.) if(present(ReadOnly)) call AUTOAddArg(invokeargs, '$ARG3', ReadOnly, .false.) if(present(Format)) call AUTOAddArg(invokeargs, '$ARG4', Format, .false.) if(present(Password)) call AUTOAddArg(invokeargs, '$ARG5', Password, .false.) if(present(WriteResPassword)) call AUTOAddArg(invokeargs, '$ARG6',
&
WriteResPassword, .false.) if(present(IgnoreReadOnlyRecommended)) call AUTOAddArg(invokeargs, '$ARG7', &
IgnoreReadOnlyRecommended, .false.) if(present(Origin)) call AUTOAddArg(invokeargs, '$ARG8', Origin, .false.) if(present(Delimiter)) call AUTOAddArg(invokeargs, '$ARG9', Delimiter, .false.) if(present(Editable)) call AUTOAddArg(invokeargs, '$ARG10', Editable, .false.) if(present(Notify)) call AUTOAddArg(invokeargs, '$ARG11', Notify, .false.) if(present(Converter)) call AUTOAddArg(invokeargs, '$ARG12', Converter, .false.)
407

О. В. Бартеньев. Современный ФОРТРАН
if(present(AddToMru)) call AUTOAddArg(invokeargs, '$ARG13', AddToMru, .false.)
$$status = AUTOinvoke($object, 682, invokeargs) if(present($status)) $status = $$status
Workbooks_Open = $return call AUTODeallocateInvokeArgs(invokeargs) end function Workbooks_Open integer(4) function $Workbook_GetActiveSheet($object, $status)
!dec$ attributes dllexport :: $Workbook_GetActiveSheet
!dec$ attributes value :: $object
!dec$ attributes reference :: $status implicit none integer(4), intent(in) :: $object
! Указатель на объект integer(4), intent(out), optional :: $status
! Статус метода integer(4) $$status, invokeargs integer(4), volatile :: $return invokeargs = AUTOAllocateInvokeArgs( ) call AUTOAddArg(invokeargs, 'ActiveSheet', $return, .true., vt_dispatch)
$$status = AUTOGetPropertyByID($object, 307, invokeargs) if(present($status)) $status = $$status
$Workbook_GetActiveSheet = $return call AUTODeallocateInvokeArgs(invokeargs) end function $Workbook_GetActiveSheet
! $Worksheet_GetRange возвращает переменную типа POINTER(p, INTEGER(4)) integer(4) function $Worksheet_GetRange($object, Cell1, Cell2, $status)
!dec$ attributes dllexport :: $Worksheet_GetRange
!dec$ attributes value :: $object
!dec$ attributes reference :: Cell1
!dec$ attributes reference :: Cell2
!dec$ attributes reference :: $status implicit none integer(4), intent(in) :: $object
! Указатель на объект type(variant), intent(in) :: Cell1 type(variant), intent(in), optional :: Cell2 integer(4), intent(out), optional :: $status
! Статус метода integer(4) $$status, invokeargs integer(4), volatile :: $return invokeargs = AUTOAllocateInvokeArgs( )
! Первая буква константы 'Range' - прописная call AUTOAddArg(invokeargs, 'Range', $return, .true., vt_dispatch)
! Константы '$ARG1', '$ARG2' записываются прописными буквами call AUTOAddArg(invokeargs, '$ARG1', Cell1, .false.) if(present(Cell2)) call AUTOAddArg(invokeargs, '$ARG2', Cell2, .false.)
$$status = AUTOGetPropertyByID($object, 197, invokeargs) if(present($status)) $status = $$status
$Worksheet_GetRange = $return call AUTODeallocateInvokeArgs(invokeargs) end function $Worksheet_GetRange
1   ...   41   42   43   44   45   46   47   48   49


написать администратору сайта